mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-01-18 14:34:17 +08:00
Removed the deprecated EIGEN2_SUPPORT, as previously announced. A compilation error is raised, if this compile-switch is defined. The documentation references to the corresponding pages from Eigen3.2 now. Also, the Eigen2 testsuite has been removed.
This commit is contained in:
parent
75e574275c
commit
324e7e8fc9
11
Eigen/Array
11
Eigen/Array
@ -1,11 +0,0 @@
|
||||
#ifndef EIGEN_ARRAY_MODULE_H
|
||||
#define EIGEN_ARRAY_MODULE_H
|
||||
|
||||
// include Core first to handle Eigen2 support macros
|
||||
#include "Core"
|
||||
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
#error The Eigen/Array header does no longer exist in Eigen3. All that functionality has moved to Eigen/Core.
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_ARRAY_MODULE_H
|
35
Eigen/Core
35
Eigen/Core
@ -244,34 +244,9 @@ inline static const char *SimdInstructionSetsInUse(void) {
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#define STAGE10_FULL_EIGEN2_API 10
|
||||
#define STAGE20_RESOLVE_API_CONFLICTS 20
|
||||
#define STAGE30_FULL_EIGEN3_API 30
|
||||
#define STAGE40_FULL_EIGEN3_STRICTNESS 40
|
||||
#define STAGE99_NO_EIGEN2_SUPPORT 99
|
||||
|
||||
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS
|
||||
#define EIGEN2_SUPPORT
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE40_FULL_EIGEN3_STRICTNESS
|
||||
#elif defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
|
||||
#define EIGEN2_SUPPORT
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
|
||||
#elif defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS
|
||||
#define EIGEN2_SUPPORT
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE20_RESOLVE_API_CONFLICTS
|
||||
#elif defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API
|
||||
#define EIGEN2_SUPPORT
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE10_FULL_EIGEN2_API
|
||||
#elif defined EIGEN2_SUPPORT
|
||||
// default to stage 3, that's what it's always meant
|
||||
#define EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
|
||||
#else
|
||||
#define EIGEN2_SUPPORT_STAGE STAGE99_NO_EIGEN2_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#undef minor
|
||||
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS || defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API || defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS || defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API || defined EIGEN2_SUPPORT
|
||||
// This will generate an error message:
|
||||
#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information
|
||||
#endif
|
||||
|
||||
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
|
||||
@ -429,8 +404,4 @@ using std::ptrdiff_t;
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "Eigen2Support"
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_CORE_H
|
||||
|
@ -1,82 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2SUPPORT_H
|
||||
#define EIGEN2SUPPORT_H
|
||||
|
||||
#if (!defined(EIGEN2_SUPPORT)) || (!defined(EIGEN_CORE_H))
|
||||
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
/** \ingroup Support_modules
|
||||
* \defgroup Eigen2Support_Module Eigen2 support module
|
||||
* This module provides a couple of deprecated functions improving the compatibility with Eigen2.
|
||||
*
|
||||
* To use it, define EIGEN2_SUPPORT before including any Eigen header
|
||||
* \code
|
||||
* #define EIGEN2_SUPPORT
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/Eigen2Support/Macros.h"
|
||||
#include "src/Eigen2Support/Memory.h"
|
||||
#include "src/Eigen2Support/Meta.h"
|
||||
#include "src/Eigen2Support/Lazy.h"
|
||||
#include "src/Eigen2Support/Cwise.h"
|
||||
#include "src/Eigen2Support/CwiseOperators.h"
|
||||
#include "src/Eigen2Support/TriangularSolver.h"
|
||||
#include "src/Eigen2Support/Block.h"
|
||||
#include "src/Eigen2Support/VectorBlock.h"
|
||||
#include "src/Eigen2Support/Minor.h"
|
||||
#include "src/Eigen2Support/MathFunctions.h"
|
||||
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
// Eigen2 used to include iostream
|
||||
#include<iostream>
|
||||
|
||||
#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
|
||||
using Eigen::Matrix##SizeSuffix##TypeSuffix; \
|
||||
using Eigen::Vector##SizeSuffix##TypeSuffix; \
|
||||
using Eigen::RowVector##SizeSuffix##TypeSuffix;
|
||||
|
||||
#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
|
||||
|
||||
#define EIGEN_USING_MATRIX_TYPEDEFS \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd)
|
||||
|
||||
#define USING_PART_OF_NAMESPACE_EIGEN \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS \
|
||||
using Eigen::Matrix; \
|
||||
using Eigen::MatrixBase; \
|
||||
using Eigen::ei_random; \
|
||||
using Eigen::ei_real; \
|
||||
using Eigen::ei_imag; \
|
||||
using Eigen::ei_conj; \
|
||||
using Eigen::ei_abs; \
|
||||
using Eigen::ei_abs2; \
|
||||
using Eigen::ei_sqrt; \
|
||||
using Eigen::ei_exp; \
|
||||
using Eigen::ei_log; \
|
||||
using Eigen::ei_sin; \
|
||||
using Eigen::ei_cos;
|
||||
|
||||
#endif // EIGEN2SUPPORT_H
|
@ -33,29 +33,23 @@
|
||||
#include "src/Geometry/OrthoMethods.h"
|
||||
#include "src/Geometry/EulerAngles.h"
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
#include "src/Geometry/Homogeneous.h"
|
||||
#include "src/Geometry/RotationBase.h"
|
||||
#include "src/Geometry/Rotation2D.h"
|
||||
#include "src/Geometry/Quaternion.h"
|
||||
#include "src/Geometry/AngleAxis.h"
|
||||
#include "src/Geometry/Transform.h"
|
||||
#include "src/Geometry/Translation.h"
|
||||
#include "src/Geometry/Scaling.h"
|
||||
#include "src/Geometry/Hyperplane.h"
|
||||
#include "src/Geometry/ParametrizedLine.h"
|
||||
#include "src/Geometry/AlignedBox.h"
|
||||
#include "src/Geometry/Umeyama.h"
|
||||
#include "src/Geometry/Homogeneous.h"
|
||||
#include "src/Geometry/RotationBase.h"
|
||||
#include "src/Geometry/Rotation2D.h"
|
||||
#include "src/Geometry/Quaternion.h"
|
||||
#include "src/Geometry/AngleAxis.h"
|
||||
#include "src/Geometry/Transform.h"
|
||||
#include "src/Geometry/Translation.h"
|
||||
#include "src/Geometry/Scaling.h"
|
||||
#include "src/Geometry/Hyperplane.h"
|
||||
#include "src/Geometry/ParametrizedLine.h"
|
||||
#include "src/Geometry/AlignedBox.h"
|
||||
#include "src/Geometry/Umeyama.h"
|
||||
|
||||
// Use the SSE optimized version whenever possible. At the moment the
|
||||
// SSE version doesn't compile when AVX is enabled
|
||||
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
|
||||
#include "src/Geometry/arch/Geometry_SSE.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "src/Eigen2Support/Geometry/All.h"
|
||||
// Use the SSE optimized version whenever possible. At the moment the
|
||||
// SSE version doesn't compile when AVX is enabled
|
||||
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
|
||||
#include "src/Geometry/arch/Geometry_SSE.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
4
Eigen/LU
4
Eigen/LU
@ -33,10 +33,6 @@
|
||||
#include "src/LU/arch/Inverse_SSE.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "src/Eigen2Support/LU.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_LU_MODULE_H
|
||||
|
@ -1,32 +0,0 @@
|
||||
#ifndef EIGEN_REGRESSION_MODULE_H
|
||||
#define EIGEN_REGRESSION_MODULE_H
|
||||
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
#error LeastSquares is only available in Eigen2 support mode (define EIGEN2_SUPPORT)
|
||||
#endif
|
||||
|
||||
// exclude from normal eigen3-only documentation
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "Eigenvalues"
|
||||
#include "Geometry"
|
||||
|
||||
/** \defgroup LeastSquares_Module LeastSquares module
|
||||
* This module provides linear regression and related features.
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/LeastSquares>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Eigen2Support/LeastSquares.h"
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
#endif // EIGEN_REGRESSION_MODULE_H
|
8
Eigen/QR
8
Eigen/QR
@ -33,15 +33,7 @@
|
||||
#include "src/QR/ColPivHouseholderQR_MKL.h"
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "src/Eigen2Support/QR.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "Eigenvalues"
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_QR_MODULE_H
|
||||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */
|
||||
|
@ -27,10 +27,6 @@
|
||||
#endif
|
||||
#include "src/SVD/UpperBidiagonalization.h"
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#include "src/Eigen2Support/SVD.h"
|
||||
#endif
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN_SVD_MODULE_H
|
||||
|
@ -151,13 +151,6 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
eigen_assert(m_isInitialized && "LDLT is not initialized.");
|
||||
return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
inline bool isPositiveDefinite() const
|
||||
{
|
||||
return isPositive();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \returns true if the matrix is negative (semidefinite) */
|
||||
inline bool isNegative(void) const
|
||||
@ -191,15 +184,6 @@ template<typename _MatrixType, int _UpLo> class LDLT
|
||||
return internal::solve_retval<LDLT, Rhs>(*this, b.derived());
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = this->solve(b);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Derived>
|
||||
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
|
@ -127,17 +127,6 @@ template<typename _MatrixType, int _UpLo> class LLT
|
||||
return internal::solve_retval<LLT, Rhs>(*this, b.derived());
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = this->solve(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isPositiveDefinite() const { return true; }
|
||||
#endif
|
||||
|
||||
template<typename Derived>
|
||||
void solveInPlace(MatrixBase<Derived> &bAndX) const;
|
||||
|
||||
|
@ -506,17 +506,6 @@ template<typename Derived> class DenseBase
|
||||
# endif
|
||||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
|
||||
Block<Derived> corner(CornerType type, Index cRows, Index cCols);
|
||||
const Block<Derived> corner(CornerType type, Index cRows, Index cCols) const;
|
||||
template<int CRows, int CCols>
|
||||
Block<Derived, CRows, CCols> corner(CornerType type);
|
||||
template<int CRows, int CCols>
|
||||
const Block<Derived, CRows, CCols> corner(CornerType type) const;
|
||||
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
|
||||
// disable the use of evalTo for dense objects with a nice compilation error
|
||||
template<typename Dest>
|
||||
|
@ -156,10 +156,8 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
|
||||
EIGEN_STRONG_INLINE CoeffReturnType
|
||||
operator[](Index index) const
|
||||
{
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
|
||||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
|
||||
#endif
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
return derived().coeff(index);
|
||||
}
|
||||
@ -388,10 +386,8 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
|
||||
EIGEN_STRONG_INLINE Scalar&
|
||||
operator[](Index index)
|
||||
{
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
|
||||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
|
||||
#endif
|
||||
eigen_assert(index >= 0 && index < size());
|
||||
return derived().coeffRef(index);
|
||||
}
|
||||
|
@ -95,21 +95,6 @@ class DiagonalBase : public EigenBase<Derived>
|
||||
{
|
||||
return other.diagonal() * scalar;
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
|
||||
{
|
||||
return diagonal().isApprox(other.diagonal(), precision);
|
||||
}
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
|
||||
{
|
||||
return toDenseMatrix().isApprox(other, precision);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
|
@ -76,34 +76,6 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
||||
return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
/** \returns the dot product of *this with other, with the Eigen2 convention that the dot product is linear in the first variable
|
||||
* (conjugating the second variable). Of course this only makes a difference in the complex case.
|
||||
*
|
||||
* This method is only available in EIGEN2_SUPPORT mode.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa dot()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename internal::traits<Derived>::Scalar
|
||||
MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
eigen_assert(size() == other.size());
|
||||
|
||||
return internal::dot_nocheck<OtherDerived,Derived>::run(other,*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//---------- implementation of L2 norm and related functions ----------
|
||||
|
||||
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
|
||||
|
@ -110,14 +110,9 @@ template<typename PlainObjectType, int MapOptions, typename StrideType> class Ma
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Map)
|
||||
|
||||
typedef typename Base::PointerType PointerType;
|
||||
#if EIGEN2_SUPPORT_STAGE <= STAGE30_FULL_EIGEN3_API
|
||||
typedef const Scalar* PointerArgType;
|
||||
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return const_cast<PointerType>(ptr); }
|
||||
#else
|
||||
typedef PointerType PointerArgType;
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; }
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline Index innerStride() const
|
||||
|
@ -366,13 +366,6 @@ class Matrix
|
||||
EIGEN_DEVICE_FUNC
|
||||
Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived>
|
||||
explicit Matrix(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
|
||||
template<typename OtherDerived>
|
||||
Matrix& operator=(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
|
||||
#endif
|
||||
|
||||
// allow to extend Matrix outside Eigen
|
||||
#ifdef EIGEN_MATRIX_PLUGIN
|
||||
#include EIGEN_MATRIX_PLUGIN
|
||||
|
@ -221,11 +221,6 @@ template<typename Derived> class MatrixBase
|
||||
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
|
||||
dot(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived>
|
||||
Scalar eigen2_dot(const MatrixBase<OtherDerived>& other) const;
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC RealScalar squaredNorm() const;
|
||||
EIGEN_DEVICE_FUNC RealScalar norm() const;
|
||||
RealScalar stableNorm() const;
|
||||
@ -269,17 +264,6 @@ template<typename Derived> class MatrixBase
|
||||
typename ConstDiagonalIndexReturnType<DynamicIndex>::Type diagonal(Index index) const;
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
|
||||
template<unsigned int Mode> const typename internal::eigen2_part_return_type<Derived, Mode>::type part() const;
|
||||
|
||||
// huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead
|
||||
// of an integer constant. Solution: overload the part() method template wrt template parameters list.
|
||||
template<template<typename T, int N> class U>
|
||||
const DiagonalWrapper<ConstDiagonalReturnType> part() const
|
||||
{ return diagonal().asDiagonal(); }
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; };
|
||||
template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; };
|
||||
|
||||
@ -373,24 +357,7 @@ template<typename Derived> class MatrixBase
|
||||
EIGEN_DEVICE_FUNC const FullPivLU<PlainObject> fullPivLu() const;
|
||||
EIGEN_DEVICE_FUNC const PartialPivLU<PlainObject> partialPivLu() const;
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
const LU<PlainObject> lu() const;
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
const LU<PlainObject> eigen2_lu() const;
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
const PartialPivLU<PlainObject> lu() const;
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename ResultType>
|
||||
void computeInverse(MatrixBase<ResultType> *result) const {
|
||||
*result = this->inverse();
|
||||
}
|
||||
#endif
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
const internal::inverse_impl<Derived> inverse() const;
|
||||
@ -419,10 +386,6 @@ template<typename Derived> class MatrixBase
|
||||
const HouseholderQR<PlainObject> householderQr() const;
|
||||
const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const;
|
||||
const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
const QR<PlainObject> qr() const;
|
||||
#endif
|
||||
|
||||
EigenvaluesReturnType eigenvalues() const;
|
||||
RealScalar operatorNorm() const;
|
||||
@ -431,10 +394,6 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
SVD<PlainObject> svd() const;
|
||||
#endif
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
@ -458,13 +417,11 @@ template<typename Derived> class MatrixBase
|
||||
|
||||
Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
ScalarMultipleReturnType operator*(const UniformScaling<Scalar>& s) const;
|
||||
// put this as separate enum value to work around possible GCC 4.3 bug (?)
|
||||
enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1?Vertical:Horizontal };
|
||||
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
|
||||
HomogeneousReturnType homogeneous() const;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SizeMinusOne = SizeAtCompileTime==Dynamic ? Dynamic : SizeAtCompileTime-1
|
||||
@ -513,41 +470,6 @@ template<typename Derived> class MatrixBase
|
||||
const MatrixPowerReturnValue<Derived> pow(const RealScalar& p) const;
|
||||
const MatrixComplexPowerReturnValue<Derived> pow(const std::complex<RealScalar>& p) const;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other);
|
||||
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other);
|
||||
|
||||
/** \deprecated because .lazy() is deprecated
|
||||
* Overloaded for cache friendly product evaluation */
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeAssigningBit>& other)
|
||||
{ return lazyAssign(other._expression()); }
|
||||
|
||||
template<unsigned int Added>
|
||||
const Flagged<Derived, Added, 0> marked() const;
|
||||
const Flagged<Derived, 0, EvalBeforeAssigningBit> lazy() const;
|
||||
|
||||
inline const Cwise<Derived> cwise() const;
|
||||
inline Cwise<Derived> cwise();
|
||||
|
||||
VectorBlock<Derived> start(Index size);
|
||||
const VectorBlock<const Derived> start(Index size) const;
|
||||
VectorBlock<Derived> end(Index size);
|
||||
const VectorBlock<const Derived> end(Index size) const;
|
||||
template<int Size> VectorBlock<Derived,Size> start();
|
||||
template<int Size> const VectorBlock<const Derived,Size> start() const;
|
||||
template<int Size> VectorBlock<Derived,Size> end();
|
||||
template<int Size> const VectorBlock<const Derived,Size> end() const;
|
||||
|
||||
Minor<Derived> minor(Index row, Index col);
|
||||
const Minor<Derived> minor(Index row, Index col) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC MatrixBase() : Base() {}
|
||||
|
||||
|
@ -85,13 +85,6 @@ template<typename T> struct GenericNumTraits
|
||||
}
|
||||
static inline T highest() { return (std::numeric_limits<T>::max)(); }
|
||||
static inline T lowest() { return IsInteger ? (std::numeric_limits<T>::min)() : (-(std::numeric_limits<T>::max)()); }
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
enum {
|
||||
HasFloatingPoint = !IsInteger
|
||||
};
|
||||
typedef NonInteger FloatingPoint;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T> struct NumTraits : GenericNumTraits<T>
|
||||
|
@ -131,17 +131,13 @@ class ProductBase : public MatrixBase<Derived>
|
||||
const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const
|
||||
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
|
||||
|
||||
// restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression
|
||||
// restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isn't an Lvalue expression
|
||||
typename Base::CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum();
|
||||
#else
|
||||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
|
||||
eigen_assert(this->rows() == 1 && this->cols() == 1);
|
||||
Matrix<Scalar,1,1> result = *this;
|
||||
return result.coeff(row,col);
|
||||
#endif
|
||||
}
|
||||
|
||||
typename Base::CoeffReturnType coeff(Index i) const
|
||||
|
@ -177,31 +177,6 @@ template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
|
||||
EigenvaluesReturnType eigenvalues() const;
|
||||
EIGEN_DEVICE_FUNC
|
||||
RealScalar operatorNorm() const;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
SelfAdjointView& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
enum {
|
||||
OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
|
||||
};
|
||||
m_matrix.const_cast_derived().template triangularView<UpLo>() = other;
|
||||
m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.adjoint();
|
||||
return *this;
|
||||
}
|
||||
template<typename OtherMatrixType, unsigned int OtherMode>
|
||||
EIGEN_DEVICE_FUNC
|
||||
SelfAdjointView& operator=(const TriangularView<OtherMatrixType, OtherMode>& other)
|
||||
{
|
||||
enum {
|
||||
OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
|
||||
};
|
||||
m_matrix.const_cast_derived().template triangularView<UpLo>() = other.toDenseMatrix();
|
||||
m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.toDenseMatrix().adjoint();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
MatrixTypeNested m_matrix;
|
||||
|
@ -342,35 +342,6 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularView
|
||||
(lhs.derived(),rhs.m_matrix);
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename OtherDerived>
|
||||
struct eigen2_product_return_type
|
||||
{
|
||||
typedef typename TriangularView<MatrixType,Mode>::DenseMatrixType DenseMatrixType;
|
||||
typedef typename OtherDerived::PlainObject::DenseType OtherPlainObject;
|
||||
typedef typename ProductReturnType<DenseMatrixType, OtherPlainObject>::Type ProdRetType;
|
||||
typedef typename ProdRetType::PlainObject type;
|
||||
};
|
||||
template<typename OtherDerived>
|
||||
const typename eigen2_product_return_type<OtherDerived>::type
|
||||
operator*(const EigenBase<OtherDerived>& rhs) const
|
||||
{
|
||||
typename OtherDerived::PlainObject::DenseType rhsPlainObject;
|
||||
rhs.evalTo(rhsPlainObject);
|
||||
return this->toDenseMatrix() * rhsPlainObject;
|
||||
}
|
||||
template<typename OtherMatrixType>
|
||||
bool isApprox(const TriangularView<OtherMatrixType, Mode>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
|
||||
{
|
||||
return this->toDenseMatrix().isApprox(other.toDenseMatrix(), precision);
|
||||
}
|
||||
template<typename OtherDerived>
|
||||
bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
|
||||
{
|
||||
return this->toDenseMatrix().isApprox(other, precision);
|
||||
}
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
template<int Side, typename Other>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline const internal::triangular_solve_retval<Side,TriangularView, Other>
|
||||
@ -780,41 +751,6 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
|
||||
* Implementation of MatrixBase methods
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
|
||||
// implementation of part<>(), including the SelfAdjoint case.
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
struct eigen2_part_return_type
|
||||
{
|
||||
typedef TriangularView<MatrixType, Mode> type;
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
struct eigen2_part_return_type<MatrixType, SelfAdjoint>
|
||||
{
|
||||
typedef SelfAdjointView<MatrixType, Upper> type;
|
||||
};
|
||||
}
|
||||
|
||||
/** \deprecated use MatrixBase::triangularView() */
|
||||
template<typename Derived>
|
||||
template<unsigned int Mode>
|
||||
const typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \deprecated use MatrixBase::triangularView() */
|
||||
template<typename Derived>
|
||||
template<unsigned int Mode>
|
||||
typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part()
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \returns an expression of a triangular view extracted from the current matrix
|
||||
*
|
||||
|
@ -560,9 +560,7 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
Homogeneous<ExpressionType,Direction> homogeneous() const;
|
||||
#endif
|
||||
|
||||
typedef typename ExpressionType::PlainObject CrossReturnType;
|
||||
template<typename OtherDerived>
|
||||
|
@ -236,35 +236,12 @@ template<typename Scalar> class Rotation2D;
|
||||
template<typename Scalar> class AngleAxis;
|
||||
template<typename Scalar,int Dim> class Translation;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename Derived, int _Dim> class eigen2_RotationBase;
|
||||
template<typename Lhs, typename Rhs> class eigen2_Cross;
|
||||
template<typename Scalar> class eigen2_Quaternion;
|
||||
template<typename Scalar> class eigen2_Rotation2D;
|
||||
template<typename Scalar> class eigen2_AngleAxis;
|
||||
template<typename Scalar,int Dim> class eigen2_Transform;
|
||||
template <typename _Scalar, int _AmbientDim> class eigen2_ParametrizedLine;
|
||||
template <typename _Scalar, int _AmbientDim> class eigen2_Hyperplane;
|
||||
template<typename Scalar,int Dim> class eigen2_Translation;
|
||||
template<typename Scalar,int Dim> class eigen2_Scaling;
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
template<typename Scalar> class Quaternion;
|
||||
template<typename Scalar,int Dim> class Transform;
|
||||
template <typename _Scalar, int _AmbientDim> class ParametrizedLine;
|
||||
template <typename _Scalar, int _AmbientDim> class Hyperplane;
|
||||
template<typename Scalar,int Dim> class Scaling;
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
template<typename Scalar, int Options = AutoAlign> class Quaternion;
|
||||
template<typename Scalar,int Dim,int Mode,int _Options=AutoAlign> class Transform;
|
||||
template <typename _Scalar, int _AmbientDim, int Options=AutoAlign> class ParametrizedLine;
|
||||
template <typename _Scalar, int _AmbientDim, int Options=AutoAlign> class Hyperplane;
|
||||
template<typename Scalar> class UniformScaling;
|
||||
template<typename MatrixType,int Direction> class Homogeneous;
|
||||
#endif
|
||||
|
||||
// MatrixFunctions module
|
||||
template<typename Derived> struct MatrixExponentialReturnValue;
|
||||
@ -283,18 +260,6 @@ struct stem_function
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
template<typename ExpressionType> class Cwise;
|
||||
template<typename MatrixType> class Minor;
|
||||
template<typename MatrixType> class LU;
|
||||
template<typename MatrixType> class QR;
|
||||
template<typename MatrixType> class SVD;
|
||||
namespace internal {
|
||||
template<typename MatrixType, unsigned int Mode> struct eigen2_part_return_type;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_FORWARDDECLARATIONS_H
|
||||
|
@ -168,13 +168,8 @@
|
||||
) \
|
||||
)
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE) \
|
||||
eigen_assert(!NumTraits<Scalar>::IsInteger);
|
||||
#else
|
||||
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE) \
|
||||
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE) \
|
||||
EIGEN_STATIC_ASSERT(!NumTraits<TYPE>::IsInteger, THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
|
||||
#endif
|
||||
|
||||
|
||||
// static assertion failing if it is guaranteed at compile-time that the two matrix expression types have different sizes
|
||||
|
@ -1,126 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_BLOCK2_H
|
||||
#define EIGEN_BLOCK2_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \returns a dynamic-size expression of a corner of *this.
|
||||
*
|
||||
* \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
|
||||
* \a Eigen::BottomLeft, \a Eigen::BottomRight.
|
||||
* \param cRows the number of rows in the corner
|
||||
* \param cCols the number of columns in the corner
|
||||
*
|
||||
* Example: \include MatrixBase_corner_enum_int_int.cpp
|
||||
* Output: \verbinclude MatrixBase_corner_enum_int_int.out
|
||||
*
|
||||
* \note Even though the returned expression has dynamic size, in the case
|
||||
* when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
|
||||
* which means that evaluating it does not cause a dynamic memory allocation.
|
||||
*
|
||||
* \sa class Block, block(Index,Index,Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Block<Derived> DenseBase<Derived>
|
||||
::corner(CornerType type, Index cRows, Index cCols)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived>(derived(), 0, 0, cRows, cCols);
|
||||
case TopRight:
|
||||
return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
|
||||
case BottomRight:
|
||||
return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is the const version of corner(CornerType, Index, Index).*/
|
||||
template<typename Derived>
|
||||
inline const Block<Derived>
|
||||
DenseBase<Derived>::corner(CornerType type, Index cRows, Index cCols) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived>(derived(), 0, 0, cRows, cCols);
|
||||
case TopRight:
|
||||
return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
|
||||
case BottomRight:
|
||||
return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns a fixed-size expression of a corner of *this.
|
||||
*
|
||||
* \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
|
||||
* \a Eigen::BottomLeft, \a Eigen::BottomRight.
|
||||
*
|
||||
* The template parameters CRows and CCols arethe number of rows and columns in the corner.
|
||||
*
|
||||
* Example: \include MatrixBase_template_int_int_corner_enum.cpp
|
||||
* Output: \verbinclude MatrixBase_template_int_int_corner_enum.out
|
||||
*
|
||||
* \sa class Block, block(Index,Index,Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int CRows, int CCols>
|
||||
inline Block<Derived, CRows, CCols>
|
||||
DenseBase<Derived>::corner(CornerType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, 0);
|
||||
case TopRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
|
||||
case BottomRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is the const version of corner<int, int>(CornerType).*/
|
||||
template<typename Derived>
|
||||
template<int CRows, int CCols>
|
||||
inline const Block<Derived, CRows, CCols>
|
||||
DenseBase<Derived>::corner(CornerType type) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, 0);
|
||||
case TopRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
|
||||
case BottomRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_BLOCK2_H
|
@ -1,8 +0,0 @@
|
||||
FILE(GLOB Eigen_Eigen2Support_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Eigen2Support_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Eigen2Support COMPONENT Devel
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY(Geometry)
|
@ -1,192 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_CWISE_H
|
||||
#define EIGEN_CWISE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise binary operation */
|
||||
#define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise unary operation */
|
||||
#define EIGEN_CWISE_UNOP_RETURN_TYPE(OP) \
|
||||
CwiseUnaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise comparison to a scalar */
|
||||
#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, \
|
||||
typename ExpressionType::ConstantReturnType >
|
||||
|
||||
/** \class Cwise
|
||||
*
|
||||
* \brief Pseudo expression providing additional coefficient-wise operations
|
||||
*
|
||||
* \param ExpressionType the type of the object on which to do coefficient-wise operations
|
||||
*
|
||||
* This class represents an expression with additional coefficient-wise features.
|
||||
* It is the return type of MatrixBase::cwise()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
* Example: \include MatrixBase_cwise_const.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise_const.out
|
||||
*
|
||||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_CWISE_PLUGIN.
|
||||
*
|
||||
* \sa MatrixBase::cwise() const, MatrixBase::cwise()
|
||||
*/
|
||||
template<typename ExpressionType> class Cwise
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename internal::traits<ExpressionType>::Scalar Scalar;
|
||||
typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
|
||||
ExpressionType, const ExpressionType&>::type ExpressionTypeNested;
|
||||
typedef CwiseUnaryOp<internal::scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
|
||||
|
||||
inline Cwise(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
inline const ExpressionType& _expression() const { return m_matrix; }
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
||||
operator/(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
/** \deprecated ArrayBase::min() */
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
|
||||
(min)(const MatrixBase<OtherDerived> &other) const
|
||||
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)(_expression(), other.derived()); }
|
||||
|
||||
/** \deprecated ArrayBase::max() */
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
|
||||
(max)(const MatrixBase<OtherDerived> &other) const
|
||||
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)(_expression(), other.derived()); }
|
||||
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op) abs() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op) abs2() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op) square() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op) cube() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op) inverse() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op) sqrt() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op) exp() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op) log() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op) cos() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op) sin() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op) pow(const Scalar& exponent) const;
|
||||
|
||||
const ScalarAddReturnType
|
||||
operator+(const Scalar& scalar) const;
|
||||
|
||||
/** \relates Cwise */
|
||||
friend const ScalarAddReturnType
|
||||
operator+(const Scalar& scalar, const Cwise& mat)
|
||||
{ return mat + scalar; }
|
||||
|
||||
ExpressionType& operator+=(const Scalar& scalar);
|
||||
|
||||
const ScalarAddReturnType
|
||||
operator-(const Scalar& scalar) const;
|
||||
|
||||
ExpressionType& operator-=(const Scalar& scalar);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator*=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator/=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
operator<(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
|
||||
operator<=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
|
||||
operator>(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
|
||||
operator==(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
// comparisons to a scalar value
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
|
||||
operator<(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
|
||||
operator<=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
|
||||
operator>(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
|
||||
operator==(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(Scalar s) const;
|
||||
|
||||
// allow to extend Cwise outside Eigen
|
||||
#ifdef EIGEN_CWISE_PLUGIN
|
||||
#include EIGEN_CWISE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
|
||||
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
|
||||
*
|
||||
* Example: \include MatrixBase_cwise_const.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise_const.out
|
||||
*
|
||||
* \sa class Cwise, cwise()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Cwise<Derived> MatrixBase<Derived>::cwise() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
|
||||
*
|
||||
* Example: \include MatrixBase_cwise.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise.out
|
||||
*
|
||||
* \sa class Cwise, cwise() const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Cwise<Derived> MatrixBase<Derived>::cwise()
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_CWISE_H
|
@ -1,298 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ARRAY_CWISE_OPERATORS_H
|
||||
#define EIGEN_ARRAY_CWISE_OPERATORS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/***************************************************************************
|
||||
* The following functions were defined in Core
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::abs() */
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op)
|
||||
Cwise<ExpressionType>::abs() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::abs2() */
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op)
|
||||
Cwise<ExpressionType>::abs2() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::exp() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op)
|
||||
Cwise<ExpressionType>::exp() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::log() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op)
|
||||
Cwise<ExpressionType>::log() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator*() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
|
||||
Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator/() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
||||
Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator*=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this * other;
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator/=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this / other;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* The following functions were defined in Array
|
||||
***************************************************************************/
|
||||
|
||||
// -- unary operators --
|
||||
|
||||
/** \deprecated ArrayBase::sqrt() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op)
|
||||
Cwise<ExpressionType>::sqrt() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::cos() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op)
|
||||
Cwise<ExpressionType>::cos() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::sin() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op)
|
||||
Cwise<ExpressionType>::sin() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::log() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)
|
||||
Cwise<ExpressionType>::pow(const Scalar& exponent) const
|
||||
{
|
||||
return EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)(_expression(), internal::scalar_pow_op<Scalar>(exponent));
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::inverse() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op)
|
||||
Cwise<ExpressionType>::inverse() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::square() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op)
|
||||
Cwise<ExpressionType>::square() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::cube() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op)
|
||||
Cwise<ExpressionType>::cube() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
// -- binary operators --
|
||||
|
||||
/** \deprecated ArrayBase::operator<() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
Cwise<ExpressionType>::operator<(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::<=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
|
||||
Cwise<ExpressionType>::operator<=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
|
||||
Cwise<ExpressionType>::operator>(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
|
||||
Cwise<ExpressionType>::operator>=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator==() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
|
||||
Cwise<ExpressionType>::operator==(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator!=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
|
||||
Cwise<ExpressionType>::operator!=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
// comparisons to scalar value
|
||||
|
||||
/** \deprecated ArrayBase::operator<(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
|
||||
Cwise<ExpressionType>::operator<(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator<=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
|
||||
Cwise<ExpressionType>::operator<=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
|
||||
Cwise<ExpressionType>::operator>(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
|
||||
Cwise<ExpressionType>::operator>=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator==(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
|
||||
Cwise<ExpressionType>::operator==(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator!=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
Cwise<ExpressionType>::operator!=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
// scalar addition
|
||||
|
||||
/** \deprecated ArrayBase::operator+(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const typename Cwise<ExpressionType>::ScalarAddReturnType
|
||||
Cwise<ExpressionType>::operator+(const Scalar& scalar) const
|
||||
{
|
||||
return typename Cwise<ExpressionType>::ScalarAddReturnType(m_matrix, internal::scalar_add_op<Scalar>(scalar));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator+=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator+=(const Scalar& scalar)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this + scalar;
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator-(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const typename Cwise<ExpressionType>::ScalarAddReturnType
|
||||
Cwise<ExpressionType>::operator-(const Scalar& scalar) const
|
||||
{
|
||||
return *this + (-scalar);
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator-=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator-=(const Scalar& scalar)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this - scalar;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ARRAY_CWISE_OPERATORS_H
|
@ -1,159 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class AlignedBox
|
||||
*
|
||||
* \brief An axis aligned box
|
||||
*
|
||||
* \param _Scalar the type of the scalar coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*
|
||||
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class AlignedBox
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Default constructor initializing a null box. */
|
||||
inline AlignedBox()
|
||||
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
||||
|
||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||
inline explicit AlignedBox(int _dim) : m_min(_dim), m_max(_dim)
|
||||
{ setNull(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max. */
|
||||
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}
|
||||
|
||||
~AlignedBox() {}
|
||||
|
||||
/** \returns the dimension in which the box holds */
|
||||
inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; }
|
||||
|
||||
/** \returns true if the box is null, i.e, empty. */
|
||||
inline bool isNull() const { return (m_min.cwise() > m_max).any(); }
|
||||
|
||||
/** Makes \c *this a null/empty box. */
|
||||
inline void setNull()
|
||||
{
|
||||
m_min.setConstant( (std::numeric_limits<Scalar>::max)());
|
||||
m_max.setConstant(-(std::numeric_limits<Scalar>::max)());
|
||||
}
|
||||
|
||||
/** \returns the minimal corner */
|
||||
inline const VectorType& (min)() const { return m_min; }
|
||||
/** \returns a non const reference to the minimal corner */
|
||||
inline VectorType& (min)() { return m_min; }
|
||||
/** \returns the maximal corner */
|
||||
inline const VectorType& (max)() const { return m_max; }
|
||||
/** \returns a non const reference to the maximal corner */
|
||||
inline VectorType& (max)() { return m_max; }
|
||||
|
||||
/** \returns true if the point \a p is inside the box \c *this. */
|
||||
inline bool contains(const VectorType& p) const
|
||||
{ return (m_min.cwise()<=p).all() && (p.cwise()<=m_max).all(); }
|
||||
|
||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||
inline bool contains(const AlignedBox& b) const
|
||||
{ return (m_min.cwise()<=(b.min)()).all() && ((b.max)().cwise()<=m_max).all(); }
|
||||
|
||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const VectorType& p)
|
||||
{ m_min = (m_min.cwise().min)(p); m_max = (m_max.cwise().max)(p); return *this; }
|
||||
|
||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const AlignedBox& b)
|
||||
{ m_min = (m_min.cwise().min)(b.m_min); m_max = (m_max.cwise().max)(b.m_max); return *this; }
|
||||
|
||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& clamp(const AlignedBox& b)
|
||||
{ m_min = (m_min.cwise().max)(b.m_min); m_max = (m_max.cwise().min)(b.m_max); return *this; }
|
||||
|
||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||
inline AlignedBox& translate(const VectorType& t)
|
||||
{ m_min += t; m_max += t; return *this; }
|
||||
|
||||
/** \returns the squared distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa exteriorDistance()
|
||||
*/
|
||||
inline Scalar squaredExteriorDistance(const VectorType& p) const;
|
||||
|
||||
/** \returns the distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa squaredExteriorDistance()
|
||||
*/
|
||||
inline Scalar exteriorDistance(const VectorType& p) const
|
||||
{ return ei_sqrt(squaredExteriorDistance(p)); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_min = (other.min)().template cast<Scalar>();
|
||||
m_max = (other.max)().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AlignedBox& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_min, m_max;
|
||||
};
|
||||
|
||||
template<typename Scalar,int AmbiantDim>
|
||||
inline Scalar AlignedBox<Scalar,AmbiantDim>::squaredExteriorDistance(const VectorType& p) const
|
||||
{
|
||||
Scalar dist2(0);
|
||||
Scalar aux;
|
||||
for (int k=0; k<dim(); ++k)
|
||||
{
|
||||
if ((aux = (p[k]-m_min[k]))<Scalar(0))
|
||||
dist2 += aux*aux;
|
||||
else if ( (aux = (m_max[k]-p[k]))<Scalar(0))
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
return dist2;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,115 +0,0 @@
|
||||
#ifndef EIGEN2_GEOMETRY_MODULE_H
|
||||
#define EIGEN2_GEOMETRY_MODULE_H
|
||||
|
||||
#include <limits>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
#include "RotationBase.h"
|
||||
#include "Rotation2D.h"
|
||||
#include "Quaternion.h"
|
||||
#include "AngleAxis.h"
|
||||
#include "Transform.h"
|
||||
#include "Translation.h"
|
||||
#include "Scaling.h"
|
||||
#include "AlignedBox.h"
|
||||
#include "Hyperplane.h"
|
||||
#include "ParametrizedLine.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define RotationBase eigen2_RotationBase
|
||||
#define Rotation2D eigen2_Rotation2D
|
||||
#define Rotation2Df eigen2_Rotation2Df
|
||||
#define Rotation2Dd eigen2_Rotation2Dd
|
||||
|
||||
#define Quaternion eigen2_Quaternion
|
||||
#define Quaternionf eigen2_Quaternionf
|
||||
#define Quaterniond eigen2_Quaterniond
|
||||
|
||||
#define AngleAxis eigen2_AngleAxis
|
||||
#define AngleAxisf eigen2_AngleAxisf
|
||||
#define AngleAxisd eigen2_AngleAxisd
|
||||
|
||||
#define Transform eigen2_Transform
|
||||
#define Transform2f eigen2_Transform2f
|
||||
#define Transform2d eigen2_Transform2d
|
||||
#define Transform3f eigen2_Transform3f
|
||||
#define Transform3d eigen2_Transform3d
|
||||
|
||||
#define Translation eigen2_Translation
|
||||
#define Translation2f eigen2_Translation2f
|
||||
#define Translation2d eigen2_Translation2d
|
||||
#define Translation3f eigen2_Translation3f
|
||||
#define Translation3d eigen2_Translation3d
|
||||
|
||||
#define Scaling eigen2_Scaling
|
||||
#define Scaling2f eigen2_Scaling2f
|
||||
#define Scaling2d eigen2_Scaling2d
|
||||
#define Scaling3f eigen2_Scaling3f
|
||||
#define Scaling3d eigen2_Scaling3d
|
||||
|
||||
#define AlignedBox eigen2_AlignedBox
|
||||
|
||||
#define Hyperplane eigen2_Hyperplane
|
||||
#define ParametrizedLine eigen2_ParametrizedLine
|
||||
|
||||
#define ei_toRotationMatrix eigen2_ei_toRotationMatrix
|
||||
#define ei_quaternion_assign_impl eigen2_ei_quaternion_assign_impl
|
||||
#define ei_transform_product_impl eigen2_ei_transform_product_impl
|
||||
|
||||
#include "RotationBase.h"
|
||||
#include "Rotation2D.h"
|
||||
#include "Quaternion.h"
|
||||
#include "AngleAxis.h"
|
||||
#include "Transform.h"
|
||||
#include "Translation.h"
|
||||
#include "Scaling.h"
|
||||
#include "AlignedBox.h"
|
||||
#include "Hyperplane.h"
|
||||
#include "ParametrizedLine.h"
|
||||
|
||||
#undef ei_toRotationMatrix
|
||||
#undef ei_quaternion_assign_impl
|
||||
#undef ei_transform_product_impl
|
||||
|
||||
#undef RotationBase
|
||||
#undef Rotation2D
|
||||
#undef Rotation2Df
|
||||
#undef Rotation2Dd
|
||||
|
||||
#undef Quaternion
|
||||
#undef Quaternionf
|
||||
#undef Quaterniond
|
||||
|
||||
#undef AngleAxis
|
||||
#undef AngleAxisf
|
||||
#undef AngleAxisd
|
||||
|
||||
#undef Transform
|
||||
#undef Transform2f
|
||||
#undef Transform2d
|
||||
#undef Transform3f
|
||||
#undef Transform3d
|
||||
|
||||
#undef Translation
|
||||
#undef Translation2f
|
||||
#undef Translation2d
|
||||
#undef Translation3f
|
||||
#undef Translation3d
|
||||
|
||||
#undef Scaling
|
||||
#undef Scaling2f
|
||||
#undef Scaling2d
|
||||
#undef Scaling3f
|
||||
#undef Scaling3d
|
||||
|
||||
#undef AlignedBox
|
||||
|
||||
#undef Hyperplane
|
||||
#undef ParametrizedLine
|
||||
|
||||
#endif // EIGEN2_GEOMETRY_MODULE_H
|
@ -1,228 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class AngleAxis
|
||||
*
|
||||
* \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c AngleAxisf for \c float
|
||||
* \li \c AngleAxisd for \c double
|
||||
*
|
||||
* \addexample AngleAxisForEuler \label How to define a rotation from Euler-angles
|
||||
*
|
||||
* Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily
|
||||
* mimic Euler-angles. Here is an example:
|
||||
* \include AngleAxis_mimic_euler.cpp
|
||||
* Output: \verbinclude AngleAxis_mimic_euler.out
|
||||
*
|
||||
* \note This class is not aimed to be used to store a rotation transformation,
|
||||
* but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
|
||||
* and transformation objects.
|
||||
*
|
||||
* \sa class Quaternion, class Transform, MatrixBase::UnitX()
|
||||
*/
|
||||
|
||||
template<typename _Scalar> struct ei_traits<AngleAxis<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
|
||||
{
|
||||
typedef RotationBase<AngleAxis<_Scalar>,3> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 3 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Quaternion<Scalar> QuaternionType;
|
||||
|
||||
protected:
|
||||
|
||||
Vector3 m_axis;
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
AngleAxis() {}
|
||||
|
||||
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
||||
* and an \a axis which must be normalized. */
|
||||
template<typename Derived>
|
||||
inline AngleAxis(Scalar angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle)
|
||||
{
|
||||
using std::sqrt;
|
||||
using std::abs;
|
||||
// since we compare against 1, this is equal to computing the relative error
|
||||
eigen_assert( abs(m_axis.derived().squaredNorm() - 1) < sqrt( NumTraits<Scalar>::dummy_precision() ) );
|
||||
}
|
||||
|
||||
/** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
|
||||
inline AngleAxis(const QuaternionType& q) { *this = q; }
|
||||
|
||||
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
|
||||
template<typename Derived>
|
||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||
|
||||
Scalar angle() const { return m_angle; }
|
||||
Scalar& angle() { return m_angle; }
|
||||
|
||||
const Vector3& axis() const { return m_axis; }
|
||||
Vector3& axis() { return m_axis; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const AngleAxis& other) const
|
||||
{ return QuaternionType(*this) * QuaternionType(other); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const QuaternionType& other) const
|
||||
{ return QuaternionType(*this) * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
|
||||
{ return a * QuaternionType(b); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Matrix3 operator* (const Matrix3& other) const
|
||||
{ return toRotationMatrix() * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline friend Matrix3 operator* (const Matrix3& a, const AngleAxis& b)
|
||||
{ return a * b.toRotationMatrix(); }
|
||||
|
||||
/** Applies rotation to vector */
|
||||
inline Vector3 operator* (const Vector3& other) const
|
||||
{ return toRotationMatrix() * other; }
|
||||
|
||||
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
|
||||
AngleAxis inverse() const
|
||||
{ return AngleAxis(-m_angle, m_axis); }
|
||||
|
||||
AngleAxis& operator=(const QuaternionType& q);
|
||||
template<typename Derived>
|
||||
AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
template<typename Derived>
|
||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
{
|
||||
m_axis = other.axis().template cast<Scalar>();
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision angle-axis type */
|
||||
typedef AngleAxis<float> AngleAxisf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision angle-axis type */
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
/** Set \c *this from a quaternion.
|
||||
* The axis is normalized.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionType& q)
|
||||
{
|
||||
Scalar n2 = q.vec().squaredNorm();
|
||||
if (n2 < precision<Scalar>()*precision<Scalar>())
|
||||
{
|
||||
m_angle = 0;
|
||||
m_axis << 1, 0, 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = 2*std::acos(q.w());
|
||||
m_axis = q.vec() / ei_sqrt(n2);
|
||||
|
||||
using std::sqrt;
|
||||
using std::abs;
|
||||
// since we compare against 1, this is equal to computing the relative error
|
||||
eigen_assert( abs(m_axis.derived().squaredNorm() - 1) < sqrt( NumTraits<Scalar>::dummy_precision() ) );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from a 3x3 rotation matrix \a mat.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
// Since a direct conversion would not be really faster,
|
||||
// let's use the robust Quaternion implementation:
|
||||
return *this = QuaternionType(mat);
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 3x3 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename AngleAxis<Scalar>::Matrix3
|
||||
AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
Matrix3 res;
|
||||
Vector3 sin_axis = ei_sin(m_angle) * m_axis;
|
||||
Scalar c = ei_cos(m_angle);
|
||||
Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
|
||||
|
||||
Scalar tmp;
|
||||
tmp = cos1_axis.x() * m_axis.y();
|
||||
res.coeffRef(0,1) = tmp - sin_axis.z();
|
||||
res.coeffRef(1,0) = tmp + sin_axis.z();
|
||||
|
||||
tmp = cos1_axis.x() * m_axis.z();
|
||||
res.coeffRef(0,2) = tmp + sin_axis.y();
|
||||
res.coeffRef(2,0) = tmp - sin_axis.y();
|
||||
|
||||
tmp = cos1_axis.y() * m_axis.z();
|
||||
res.coeffRef(1,2) = tmp - sin_axis.x();
|
||||
res.coeffRef(2,1) = tmp + sin_axis.x();
|
||||
|
||||
res.diagonal() = (cos1_axis.cwise() * m_axis).cwise() + c;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,6 +0,0 @@
|
||||
FILE(GLOB Eigen_Eigen2Support_Geometry_SRCS "*.h")
|
||||
|
||||
INSTALL(FILES
|
||||
${Eigen_Eigen2Support_Geometry_SRCS}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/Eigen2Support/Geometry
|
||||
)
|
@ -1,254 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Hyperplane
|
||||
*
|
||||
* \brief A hyperplane
|
||||
*
|
||||
* A hyperplane is an affine subspace of dimension n-1 in a space of dimension n.
|
||||
* For example, a hyperplane in a plane is a line; a hyperplane in 3-space is a plane.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
* Notice that the dimension of the hyperplane is _AmbientDim-1.
|
||||
*
|
||||
* This class represents an hyperplane as the zero set of the implicit equation
|
||||
* \f$ n \cdot x + d = 0 \f$ where \f$ n \f$ is a unit normal vector of the plane (linear part)
|
||||
* and \f$ d \f$ is the distance (offset) to the origin.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class Hyperplane
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
typedef Matrix<Scalar,int(AmbientDimAtCompileTime)==Dynamic
|
||||
? Dynamic
|
||||
: int(AmbientDimAtCompileTime)+1,1> Coefficients;
|
||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline Hyperplane() {}
|
||||
|
||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit Hyperplane(int _dim) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = -e.eigen2_dot(n);
|
||||
}
|
||||
|
||||
/** Constructs a plane from its normal \a n and distance to the origin \a d
|
||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, Scalar d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = d;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
result.offset() = -result.normal().eigen2_dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p2 - p0).cross(p1 - p0).normalized();
|
||||
result.offset() = -result.normal().eigen2_dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the parametrized line \a parametrized.
|
||||
* If the dimension of the ambient space is greater than 2, then there isn't uniqueness,
|
||||
* so an arbitrary choice is made.
|
||||
*/
|
||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
||||
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -normal().eigen2_dot(parametrized.origin());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline int dim() const { return int(AmbientDimAtCompileTime)==Dynamic ? m_coeffs.size()-1 : int(AmbientDimAtCompileTime); }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
* \sa absDistance()
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return p.eigen2_dot(normal()) + offset(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
* \sa signedDistance()
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { return ei_abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline const NormalReturnType normal() const { return NormalReturnType(*const_cast<Coefficients*>(&m_coeffs),0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
* \warning The ambient space must be a plane, i.e. have dimension 2, so that \c *this and \a other are lines.
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(ei_isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(ei_abs(coeffs().coeff(1))>ei_abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
}
|
||||
else
|
||||
{ // general case
|
||||
Scalar invdet = Scalar(1) / det;
|
||||
return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
|
||||
invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param mat the Dim x Dim transformation matrix
|
||||
* \param traits specifies whether the matrix \a mat represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
*/
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Hyperplane::transform()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param t the transformation of dimension Dim
|
||||
* \param traits specifies whether the transformation \a t represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
* Other kind of transformations are not supported.
|
||||
*/
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
offset() -= t.translation().eigen2_dot(normal());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Hyperplane& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
@ -1,141 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class ParametrizedLine
|
||||
*
|
||||
* \brief A parametrized line
|
||||
*
|
||||
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
||||
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
||||
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ l \in \mathbf{R} \f$.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class ParametrizedLine
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline ParametrizedLine() {}
|
||||
|
||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit ParametrizedLine(int _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
|
||||
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||
* \warning the vector direction is assumed to be normalized.
|
||||
*/
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
/** Constructs a parametrized line going from \a p0 to \a p1. */
|
||||
static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||
|
||||
~ParametrizedLine() {}
|
||||
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline int dim() const { return m_direction.size(); }
|
||||
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p-origin();
|
||||
return (diff - diff.eigen2_dot(direction())* direction()).squaredNorm();
|
||||
}
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { return ei_sqrt(squaredDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the line \c *this. */
|
||||
VectorType projection(const VectorType& p) const
|
||||
{ return origin() + (p-origin()).eigen2_dot(direction()) * direction(); }
|
||||
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_origin = other.origin().template cast<Scalar>();
|
||||
m_direction = other.direction().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_origin, m_direction;
|
||||
};
|
||||
|
||||
/** Constructs a parametrized line from a 2D hyperplane
|
||||
*
|
||||
* \warning the ambient space must have dimension 2 such that the hyperplane actually describes a line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline ParametrizedLine<_Scalar, _AmbientDim>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
direction() = hyperplane.normal().unitOrthogonal();
|
||||
origin() = -hyperplane.normal()*hyperplane.offset();
|
||||
}
|
||||
|
||||
/** \returns the parameter value of the intersection between \c *this and the given hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim>::intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
{
|
||||
return -(hyperplane.offset()+origin().eigen2_dot(hyperplane.normal()))
|
||||
/(direction().eigen2_dot(hyperplane.normal()));
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,495 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename Other,
|
||||
int OtherRows=Other::RowsAtCompileTime,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_quaternion_assign_impl;
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Quaternion
|
||||
*
|
||||
* \brief The quaternion class used to represent 3D orientations and rotations
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
*
|
||||
* This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
|
||||
* orientations and rotations of objects in three dimensions. Compared to other representations
|
||||
* like Euler angles or 3x3 matrices, quatertions offer the following advantages:
|
||||
* \li \b compact storage (4 scalars)
|
||||
* \li \b efficient to compose (28 flops),
|
||||
* \li \b stable spherical interpolation
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c Quaternionf for \c float
|
||||
* \li \c Quaterniond for \c double
|
||||
*
|
||||
* \sa class AngleAxis, class Transform
|
||||
*/
|
||||
|
||||
template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
|
||||
{
|
||||
typedef RotationBase<Quaternion<_Scalar>,3> Base;
|
||||
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4)
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/** the type of the Coefficients 4-vector */
|
||||
typedef Matrix<Scalar, 4, 1> Coefficients;
|
||||
/** the type of a 3D vector */
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
/** the equivalent rotation matrix type */
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
/** the equivalent angle-axis type */
|
||||
typedef AngleAxis<Scalar> AngleAxisType;
|
||||
|
||||
/** \returns the \c x coefficient */
|
||||
inline Scalar x() const { return m_coeffs.coeff(0); }
|
||||
/** \returns the \c y coefficient */
|
||||
inline Scalar y() const { return m_coeffs.coeff(1); }
|
||||
/** \returns the \c z coefficient */
|
||||
inline Scalar z() const { return m_coeffs.coeff(2); }
|
||||
/** \returns the \c w coefficient */
|
||||
inline Scalar w() const { return m_coeffs.coeff(3); }
|
||||
|
||||
/** \returns a reference to the \c x coefficient */
|
||||
inline Scalar& x() { return m_coeffs.coeffRef(0); }
|
||||
/** \returns a reference to the \c y coefficient */
|
||||
inline Scalar& y() { return m_coeffs.coeffRef(1); }
|
||||
/** \returns a reference to the \c z coefficient */
|
||||
inline Scalar& z() { return m_coeffs.coeffRef(2); }
|
||||
/** \returns a reference to the \c w coefficient */
|
||||
inline Scalar& w() { return m_coeffs.coeffRef(3); }
|
||||
|
||||
/** \returns a read-only vector expression of the imaginary part (x,y,z) */
|
||||
inline const Block<const Coefficients,3,1> vec() const { return m_coeffs.template start<3>(); }
|
||||
|
||||
/** \returns a vector expression of the imaginary part (x,y,z) */
|
||||
inline Block<Coefficients,3,1> vec() { return m_coeffs.template start<3>(); }
|
||||
|
||||
/** \returns a read-only vector expression of the coefficients (x,y,z,w) */
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
|
||||
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||
* its four coefficients \a w, \a x, \a y and \a z.
|
||||
*
|
||||
* \warning Note the order of the arguments: the real \a w coefficient first,
|
||||
* while internally the coefficients are stored in the following order:
|
||||
* [\c x, \c y, \c z, \c w]
|
||||
*/
|
||||
inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z)
|
||||
{ m_coeffs << x, y, z, w; }
|
||||
|
||||
/** Copy constructor */
|
||||
inline Quaternion(const Quaternion& other) { m_coeffs = other.m_coeffs; }
|
||||
|
||||
/** Constructs and initializes a quaternion from the angle-axis \a aa */
|
||||
explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
|
||||
|
||||
/** Constructs and initializes a quaternion from either:
|
||||
* - a rotation matrix expression,
|
||||
* - a 4D vector expression representing quaternion coefficients.
|
||||
* \sa operator=(MatrixBase<Derived>)
|
||||
*/
|
||||
template<typename Derived>
|
||||
explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
|
||||
|
||||
Quaternion& operator=(const Quaternion& other);
|
||||
Quaternion& operator=(const AngleAxisType& aa);
|
||||
template<typename Derived>
|
||||
Quaternion& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
/** \returns a quaternion representing an identity rotation
|
||||
* \sa MatrixBase::Identity()
|
||||
*/
|
||||
static inline Quaternion Identity() { return Quaternion(1, 0, 0, 0); }
|
||||
|
||||
/** \sa Quaternion::Identity(), MatrixBase::setIdentity()
|
||||
*/
|
||||
inline Quaternion& setIdentity() { m_coeffs << 0, 0, 0, 1; return *this; }
|
||||
|
||||
/** \returns the squared norm of the quaternion's coefficients
|
||||
* \sa Quaternion::norm(), MatrixBase::squaredNorm()
|
||||
*/
|
||||
inline Scalar squaredNorm() const { return m_coeffs.squaredNorm(); }
|
||||
|
||||
/** \returns the norm of the quaternion's coefficients
|
||||
* \sa Quaternion::squaredNorm(), MatrixBase::norm()
|
||||
*/
|
||||
inline Scalar norm() const { return m_coeffs.norm(); }
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
* \sa normalized(), MatrixBase::normalize() */
|
||||
inline void normalize() { m_coeffs.normalize(); }
|
||||
/** \returns a normalized version of \c *this
|
||||
* \sa normalize(), MatrixBase::normalized() */
|
||||
inline Quaternion normalized() const { return Quaternion(m_coeffs.normalized()); }
|
||||
|
||||
/** \returns the dot product of \c *this and \a other
|
||||
* Geometrically speaking, the dot product of two unit quaternions
|
||||
* corresponds to the cosine of half the angle between the two rotations.
|
||||
* \sa angularDistance()
|
||||
*/
|
||||
inline Scalar eigen2_dot(const Quaternion& other) const { return m_coeffs.eigen2_dot(other.m_coeffs); }
|
||||
|
||||
inline Scalar angularDistance(const Quaternion& other) const;
|
||||
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
Quaternion& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
inline Quaternion operator* (const Quaternion& q) const;
|
||||
inline Quaternion& operator*= (const Quaternion& q);
|
||||
|
||||
Quaternion inverse(void) const;
|
||||
Quaternion conjugate(void) const;
|
||||
|
||||
Quaternion slerp(Scalar t, const Quaternion& other) const;
|
||||
|
||||
template<typename Derived>
|
||||
Vector3 operator* (const MatrixBase<Derived>& vec) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Quaternion(const Quaternion<OtherScalarType>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Quaternion& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision quaternion type */
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
// Generic Quaternion * Quaternion product
|
||||
template<typename Scalar> inline Quaternion<Scalar>
|
||||
ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
|
||||
{
|
||||
return Quaternion<Scalar>
|
||||
(
|
||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
||||
a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
|
||||
a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
|
||||
a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
|
||||
);
|
||||
}
|
||||
|
||||
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const
|
||||
{
|
||||
return ei_quaternion_product(*this,other);
|
||||
}
|
||||
|
||||
/** \sa operator*(Quaternion) */
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator*= (const Quaternion& other)
|
||||
{
|
||||
return (*this = *this * other);
|
||||
}
|
||||
|
||||
/** Rotation of a vector by a quaternion.
|
||||
* \remarks If the quaternion is used to rotate several points (>1)
|
||||
* then it is much more efficient to first convert it to a 3x3 Matrix.
|
||||
* Comparison of the operation cost for n transformations:
|
||||
* - Quaternion: 30n
|
||||
* - Via a Matrix3: 24 + 15n
|
||||
*/
|
||||
template <typename Scalar>
|
||||
template<typename Derived>
|
||||
inline typename Quaternion<Scalar>::Vector3
|
||||
Quaternion<Scalar>::operator* (const MatrixBase<Derived>& v) const
|
||||
{
|
||||
// Note that this algorithm comes from the optimization by hand
|
||||
// of the conversion to a Matrix followed by a Matrix/Vector product.
|
||||
// It appears to be much faster than the common algorithm found
|
||||
// in the litterature (30 versus 39 flops). It also requires two
|
||||
// Vector3 as temporaries.
|
||||
Vector3 uv;
|
||||
uv = 2 * this->vec().cross(v);
|
||||
return v + this->w() * uv + this->vec().cross(uv);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const Quaternion& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
|
||||
*/
|
||||
template<typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const AngleAxisType& aa)
|
||||
{
|
||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||
this->w() = ei_cos(ha);
|
||||
this->vec() = ei_sin(ha) * aa.axis();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from the expression \a xpr:
|
||||
* - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion
|
||||
* - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
|
||||
* and \a xpr is converted to a quaternion
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const MatrixBase<Derived>& xpr)
|
||||
{
|
||||
ei_quaternion_assign_impl<Derived>::run(*this, xpr.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Convert the quaternion to a 3x3 rotation matrix */
|
||||
template<typename Scalar>
|
||||
inline typename Quaternion<Scalar>::Matrix3
|
||||
Quaternion<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
// NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
|
||||
// if not inlined then the cost of the return by value is huge ~ +35%,
|
||||
// however, not inlining this function is an order of magnitude slower, so
|
||||
// it has to be inlined, and so the return by value is not an issue
|
||||
Matrix3 res;
|
||||
|
||||
const Scalar tx = Scalar(2)*this->x();
|
||||
const Scalar ty = Scalar(2)*this->y();
|
||||
const Scalar tz = Scalar(2)*this->z();
|
||||
const Scalar twx = tx*this->w();
|
||||
const Scalar twy = ty*this->w();
|
||||
const Scalar twz = tz*this->w();
|
||||
const Scalar txx = tx*this->x();
|
||||
const Scalar txy = ty*this->x();
|
||||
const Scalar txz = tz*this->x();
|
||||
const Scalar tyy = ty*this->y();
|
||||
const Scalar tyz = tz*this->y();
|
||||
const Scalar tzz = tz*this->z();
|
||||
|
||||
res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
|
||||
res.coeffRef(0,1) = txy-twz;
|
||||
res.coeffRef(0,2) = txz+twy;
|
||||
res.coeffRef(1,0) = txy+twz;
|
||||
res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
|
||||
res.coeffRef(1,2) = tyz-twx;
|
||||
res.coeffRef(2,0) = txz-twy;
|
||||
res.coeffRef(2,1) = tyz+twx;
|
||||
res.coeffRef(2,2) = Scalar(1)-(txx+tyy);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Sets *this to be a quaternion representing a rotation sending the vector \a a to the vector \a b.
|
||||
*
|
||||
* \returns a reference to *this.
|
||||
*
|
||||
* Note that the two input vectors do \b not have to be normalized.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived1, typename Derived2>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
Vector3 v0 = a.normalized();
|
||||
Vector3 v1 = b.normalized();
|
||||
Scalar c = v0.eigen2_dot(v1);
|
||||
|
||||
// if dot == 1, vectors are the same
|
||||
if (ei_isApprox(c,Scalar(1)))
|
||||
{
|
||||
// set to identity
|
||||
this->w() = 1; this->vec().setZero();
|
||||
return *this;
|
||||
}
|
||||
// if dot == -1, vectors are opposites
|
||||
if (ei_isApprox(c,Scalar(-1)))
|
||||
{
|
||||
this->vec() = v0.unitOrthogonal();
|
||||
this->w() = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3 axis = v0.cross(v1);
|
||||
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
|
||||
Scalar invs = Scalar(1)/s;
|
||||
this->vec() = axis * invs;
|
||||
this->w() = s * Scalar(0.5);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the multiplicative inverse of \c *this
|
||||
* Note that in most cases, i.e., if you simply want the opposite rotation,
|
||||
* and/or the quaternion is normalized, then it is enough to use the conjugate.
|
||||
*
|
||||
* \sa Quaternion::conjugate()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::inverse() const
|
||||
{
|
||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||
Scalar n2 = this->squaredNorm();
|
||||
if (n2 > 0)
|
||||
return Quaternion(conjugate().coeffs() / n2);
|
||||
else
|
||||
{
|
||||
// return an invalid result to flag the error
|
||||
return Quaternion(Coefficients::Zero());
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse
|
||||
* if the quaternion is normalized.
|
||||
* The conjugate of a quaternion represents the opposite rotation.
|
||||
*
|
||||
* \sa Quaternion::inverse()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::conjugate() const
|
||||
{
|
||||
return Quaternion(this->w(),-this->x(),-this->y(),-this->z());
|
||||
}
|
||||
|
||||
/** \returns the angle (in radian) between two rotations
|
||||
* \sa eigen2_dot()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
|
||||
{
|
||||
double d = ei_abs(this->eigen2_dot(other));
|
||||
if (d>=1.0)
|
||||
return 0;
|
||||
return Scalar(2) * std::acos(d);
|
||||
}
|
||||
|
||||
/** \returns the spherical linear interpolation between the two quaternions
|
||||
* \c *this and \a other at the parameter \a t
|
||||
*/
|
||||
template <typename Scalar>
|
||||
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
|
||||
{
|
||||
static const Scalar one = Scalar(1) - machine_epsilon<Scalar>();
|
||||
Scalar d = this->eigen2_dot(other);
|
||||
Scalar absD = ei_abs(d);
|
||||
|
||||
Scalar scale0;
|
||||
Scalar scale1;
|
||||
|
||||
if (absD>=one)
|
||||
{
|
||||
scale0 = Scalar(1) - t;
|
||||
scale1 = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
// theta is the angle between the 2 quaternions
|
||||
Scalar theta = std::acos(absD);
|
||||
Scalar sinTheta = ei_sin(theta);
|
||||
|
||||
scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||
scale1 = ei_sin( ( t * theta) ) / sinTheta;
|
||||
if (d<0)
|
||||
scale1 = -scale1;
|
||||
}
|
||||
|
||||
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
||||
}
|
||||
|
||||
// set from a rotation matrix
|
||||
template<typename Other>
|
||||
struct ei_quaternion_assign_impl<Other,3,3>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
static inline void run(Quaternion<Scalar>& q, const Other& mat)
|
||||
{
|
||||
// This algorithm comes from "Quaternion Calculus and Fast Animation",
|
||||
// Ken Shoemake, 1987 SIGGRAPH course notes
|
||||
Scalar t = mat.trace();
|
||||
if (t > 0)
|
||||
{
|
||||
t = ei_sqrt(t + Scalar(1.0));
|
||||
q.w() = Scalar(0.5)*t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
|
||||
q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
|
||||
q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
if (mat.coeff(1,1) > mat.coeff(0,0))
|
||||
i = 1;
|
||||
if (mat.coeff(2,2) > mat.coeff(i,i))
|
||||
i = 2;
|
||||
int j = (i+1)%3;
|
||||
int k = (j+1)%3;
|
||||
|
||||
t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
|
||||
q.coeffs().coeffRef(i) = Scalar(0.5) * t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
|
||||
q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
|
||||
q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// set from a vector of coefficients assumed to be a quaternion
|
||||
template<typename Other>
|
||||
struct ei_quaternion_assign_impl<Other,4,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
static inline void run(Quaternion<Scalar>& q, const Other& vec)
|
||||
{
|
||||
q.coeffs() = vec;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
@ -1,145 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Rotation2D
|
||||
*
|
||||
* \brief Represents a rotation/orientation in a 2 dimensional space.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
*
|
||||
* This class is equivalent to a single scalar representing a counter clock wise rotation
|
||||
* as a single angle in radian. It provides some additional features such as the automatic
|
||||
* conversion from/to a 2x2 rotation matrix. Moreover this class aims to provide a similar
|
||||
* interface to Quaternion in order to facilitate the writing of generic algorithms
|
||||
* dealing with rotations.
|
||||
*
|
||||
* \sa class Quaternion, class Transform
|
||||
*/
|
||||
template<typename _Scalar> struct ei_traits<Rotation2D<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class Rotation2D : public RotationBase<Rotation2D<_Scalar>,2>
|
||||
{
|
||||
typedef RotationBase<Rotation2D<_Scalar>,2> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 2 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
typedef Matrix<Scalar,2,2> Matrix2;
|
||||
|
||||
protected:
|
||||
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
||||
inline Rotation2D(Scalar a) : m_angle(a) {}
|
||||
|
||||
/** \returns the rotation angle */
|
||||
inline Scalar angle() const { return m_angle; }
|
||||
|
||||
/** \returns a read-write reference to the rotation angle */
|
||||
inline Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Rotation2D inverse() const { return -m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D operator*(const Rotation2D& other) const
|
||||
{ return m_angle + other.m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
{ return m_angle += other.m_angle; return *this; }
|
||||
|
||||
/** Applies the rotation to a 2D vector */
|
||||
Vector2 operator* (const Vector2& vec) const
|
||||
{ return toRotationMatrix() * vec; }
|
||||
|
||||
template<typename Derived>
|
||||
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix2 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns the spherical interpolation between \c *this and \a other using
|
||||
* parameter \a t. It is in fact equivalent to a linear interpolation.
|
||||
*/
|
||||
inline Rotation2D slerp(Scalar t, const Rotation2D& other) const
|
||||
{ return m_angle * (1-t) + other.angle() * t; }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
{
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Rotation2D& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision 2D rotation type */
|
||||
typedef Rotation2D<float> Rotation2Df;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision 2D rotation type */
|
||||
typedef Rotation2D<double> Rotation2Dd;
|
||||
|
||||
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
||||
* In other words, this function extract the rotation angle
|
||||
* from the rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_angle = ei_atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 2x2 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename Rotation2D<Scalar>::Matrix2
|
||||
Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
Scalar sinA = ei_sin(m_angle);
|
||||
Scalar cosA = ei_cos(m_angle);
|
||||
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,123 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// this file aims to contains the various representations of rotation/orientation
|
||||
// in 2D and 3D space excepted Matrix and Quaternion.
|
||||
|
||||
/** \class RotationBase
|
||||
*
|
||||
* \brief Common base class for compact rotation representations
|
||||
*
|
||||
* \param Derived is the derived type, i.e., a rotation type
|
||||
* \param _Dim the dimension of the space
|
||||
*/
|
||||
template<typename Derived, int _Dim>
|
||||
class RotationBase
|
||||
{
|
||||
public:
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> RotationMatrixType;
|
||||
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
/** \returns an equivalent rotation matrix */
|
||||
inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Derived inverse() const { return derived().inverse(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a translation \a t */
|
||||
inline Transform<Scalar,Dim> operator*(const Translation<Scalar,Dim>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a scaling \a s */
|
||||
inline RotationMatrixType operator*(const Scaling<Scalar,Dim>& s) const
|
||||
{ return toRotationMatrix() * s; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with an affine transformation \a t */
|
||||
inline Transform<Scalar,Dim> operator*(const Transform<Scalar,Dim>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
};
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* Constructs a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
*this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* Set a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
return *this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* Helper function to return an arbitrary rotation object to a rotation matrix.
|
||||
*
|
||||
* \param Scalar the numeric type of the matrix coefficients
|
||||
* \param Dim the dimension of the current space
|
||||
*
|
||||
* It returns a Dim x Dim fixed size matrix.
|
||||
*
|
||||
* Default specializations are provided for:
|
||||
* - any scalar type (2D),
|
||||
* - any matrix expression,
|
||||
* - any type based on RotationBase (e.g., Quaternion, AngleAxis, Rotation2D)
|
||||
*
|
||||
* Currently ei_toRotationMatrix is only used by Transform.
|
||||
*
|
||||
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
static inline Matrix<Scalar,2,2> ei_toRotationMatrix(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline Matrix<Scalar,Dim,Dim> ei_toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
|
||||
{
|
||||
return r.toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline const MatrixBase<OtherDerived>& ei_toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return mat;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,167 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Scaling
|
||||
*
|
||||
* \brief Represents a possibly non uniform scaling transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a scaling transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Translation, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Scaling
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** corresponding vector type */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** corresponding translation type */
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
/** corresponding affine transformation type */
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_coeffs;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Scaling() {}
|
||||
/** Constructs and initialize a uniform scaling transformation */
|
||||
explicit inline Scaling(const Scalar& s) { m_coeffs.setConstant(s); }
|
||||
/** 2D only */
|
||||
inline Scaling(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
ei_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** 3D only */
|
||||
inline Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
ei_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the scaling transformation from a vector of scaling coefficients */
|
||||
explicit inline Scaling(const VectorType& coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
const VectorType& coeffs() const { return m_coeffs; }
|
||||
VectorType& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two scaling */
|
||||
inline Scaling operator* (const Scaling& other) const
|
||||
{ return Scaling(coeffs().cwise() * other.coeffs()); }
|
||||
|
||||
/** Concatenates a scaling and a translation */
|
||||
inline TransformType operator* (const TranslationType& t) const;
|
||||
|
||||
/** Concatenates a scaling and an affine transformation */
|
||||
inline TransformType operator* (const TransformType& t) const;
|
||||
|
||||
/** Concatenates a scaling and a linear transformation matrix */
|
||||
// TODO returns an expression
|
||||
inline LinearMatrixType operator* (const LinearMatrixType& other) const
|
||||
{ return coeffs().asDiagonal() * other; }
|
||||
|
||||
/** Concatenates a linear transformation matrix and a scaling */
|
||||
// TODO returns an expression
|
||||
friend inline LinearMatrixType operator* (const LinearMatrixType& other, const Scaling& s)
|
||||
{ return other * s.coeffs().asDiagonal(); }
|
||||
|
||||
template<typename Derived>
|
||||
inline LinearMatrixType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * r.toRotationMatrix(); }
|
||||
|
||||
/** Applies scaling to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return coeffs().asDiagonal() * other; }
|
||||
|
||||
/** \returns the inverse scaling */
|
||||
inline Scaling inverse() const
|
||||
{ return Scaling(coeffs().cwise().inverse()); }
|
||||
|
||||
inline Scaling& operator=(const Scaling& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Scaling(const Scaling<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Scaling& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Scaling<float, 2> Scaling2f;
|
||||
typedef Scaling<double,2> Scaling2d;
|
||||
typedef Scaling<float, 3> Scaling3f;
|
||||
typedef Scaling<double,3> Scaling3d;
|
||||
//@}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Scaling<Scalar,Dim>::TransformType
|
||||
Scaling<Scalar,Dim>::operator* (const TranslationType& t) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal() = coeffs();
|
||||
res.translation() = m_coeffs.cwise() * t.vector();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Scaling<Scalar,Dim>::TransformType
|
||||
Scaling<Scalar,Dim>::operator* (const TransformType& t) const
|
||||
{
|
||||
TransformType res = t;
|
||||
res.prescale(m_coeffs);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,786 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// Note that we have to pass Dim and HDim because it is not allowed to use a template
|
||||
// parameter to define a template specialization. To be more precise, in the following
|
||||
// specializations, it is not allowed to use Dim+1 instead of HDim.
|
||||
template< typename Other,
|
||||
int Dim,
|
||||
int HDim,
|
||||
int OtherRows=Other::RowsAtCompileTime,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_transform_product_impl;
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Transform
|
||||
*
|
||||
* \brief Represents an homogeneous transformation in a N dimensional space
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _Dim the dimension of the space
|
||||
*
|
||||
* The homography is internally represented and stored as a (Dim+1)^2 matrix which
|
||||
* is available through the matrix() method.
|
||||
*
|
||||
* Conversion methods from/to Qt's QMatrix and QTransform are available if the
|
||||
* preprocessor token EIGEN_QT_SUPPORT is defined.
|
||||
*
|
||||
* \sa class Matrix, class Quaternion
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Transform
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
|
||||
enum {
|
||||
Dim = _Dim, ///< space dimension in which the transformation holds
|
||||
HDim = _Dim+1 ///< size of a respective homogeneous vector
|
||||
};
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** type of the matrix used to represent the transformation */
|
||||
typedef Matrix<Scalar,HDim,HDim> MatrixType;
|
||||
/** type of the matrix used to represent the linear part of the transformation */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** type of read/write reference to the linear part of the transformation */
|
||||
typedef Block<MatrixType,Dim,Dim> LinearPart;
|
||||
/** type of read/write reference to the linear part of the transformation */
|
||||
typedef const Block<const MatrixType,Dim,Dim> ConstLinearPart;
|
||||
/** type of a vector */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** type of a read/write reference to the translation part of the rotation */
|
||||
typedef Block<MatrixType,Dim,1> TranslationPart;
|
||||
/** type of a read/write reference to the translation part of the rotation */
|
||||
typedef const Block<const MatrixType,Dim,1> ConstTranslationPart;
|
||||
/** corresponding translation type */
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
/** corresponding scaling transformation type */
|
||||
typedef Scaling<Scalar,Dim> ScalingType;
|
||||
|
||||
protected:
|
||||
|
||||
MatrixType m_matrix;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization of the coefficients. */
|
||||
inline Transform() { }
|
||||
|
||||
inline Transform(const Transform& other)
|
||||
{
|
||||
m_matrix = other.m_matrix;
|
||||
}
|
||||
|
||||
inline explicit Transform(const TranslationType& t) { *this = t; }
|
||||
inline explicit Transform(const ScalingType& s) { *this = s; }
|
||||
template<typename Derived>
|
||||
inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
|
||||
|
||||
inline Transform& operator=(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; return *this; }
|
||||
|
||||
template<typename OtherDerived, bool BigMatrix> // MSVC 2005 will commit suicide if BigMatrix has a default value
|
||||
struct construct_from_matrix
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
transform->matrix() = other;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename OtherDerived> struct construct_from_matrix<OtherDerived, true>
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
transform->linear() = other;
|
||||
transform->translation().setZero();
|
||||
transform->matrix()(Dim,Dim) = Scalar(1);
|
||||
transform->matrix().template block<1,Dim>(Dim,0).setZero();
|
||||
}
|
||||
};
|
||||
|
||||
/** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline explicit Transform(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
|
||||
}
|
||||
|
||||
/** Set \c *this from a (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline Transform& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{ m_matrix = other; return *this; }
|
||||
|
||||
#ifdef EIGEN_QT_SUPPORT
|
||||
inline Transform(const QMatrix& other);
|
||||
inline Transform& operator=(const QMatrix& other);
|
||||
inline QMatrix toQMatrix(void) const;
|
||||
inline Transform(const QTransform& other);
|
||||
inline Transform& operator=(const QTransform& other);
|
||||
inline QTransform toQTransform(void) const;
|
||||
#endif
|
||||
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operaror(int,int) const */
|
||||
inline Scalar operator() (int row, int col) const { return m_matrix(row,col); }
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operaror(int,int) */
|
||||
inline Scalar& operator() (int row, int col) { return m_matrix(row,col); }
|
||||
|
||||
/** \returns a read-only expression of the transformation matrix */
|
||||
inline const MatrixType& matrix() const { return m_matrix; }
|
||||
/** \returns a writable expression of the transformation matrix */
|
||||
inline MatrixType& matrix() { return m_matrix; }
|
||||
|
||||
/** \returns a read-only expression of the linear (linear) part of the transformation */
|
||||
inline ConstLinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
|
||||
/** \returns a writable expression of the linear (linear) part of the transformation */
|
||||
inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
|
||||
|
||||
/** \returns a read-only expression of the translation vector of the transformation */
|
||||
inline ConstTranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
|
||||
/** \returns a writable expression of the translation vector of the transformation */
|
||||
inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
|
||||
|
||||
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other
|
||||
*
|
||||
* The right hand side \a other might be either:
|
||||
* \li a vector of size Dim,
|
||||
* \li an homogeneous vector of size Dim+1,
|
||||
* \li a transformation matrix of size Dim+1 x Dim+1.
|
||||
*/
|
||||
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||
template<typename OtherDerived>
|
||||
inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
|
||||
operator * (const MatrixBase<OtherDerived> &other) const
|
||||
{ return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
|
||||
|
||||
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
||||
* The transformation matrix \a a must have a Dim+1 x Dim+1 sizes. */
|
||||
template<typename OtherDerived>
|
||||
friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
|
||||
operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
|
||||
{ return a.derived() * b.matrix(); }
|
||||
|
||||
/** Contatenates two transformations */
|
||||
inline const Transform
|
||||
operator * (const Transform& other) const
|
||||
{ return Transform(m_matrix * other.matrix()); }
|
||||
|
||||
/** \sa MatrixBase::setIdentity() */
|
||||
void setIdentity() { m_matrix.setIdentity(); }
|
||||
static const typename MatrixType::IdentityReturnType Identity()
|
||||
{
|
||||
return MatrixType::Identity();
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
inline Transform& scale(Scalar s);
|
||||
inline Transform& prescale(Scalar s);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& translate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename RotationType>
|
||||
inline Transform& rotate(const RotationType& rotation);
|
||||
|
||||
template<typename RotationType>
|
||||
inline Transform& prerotate(const RotationType& rotation);
|
||||
|
||||
Transform& shear(Scalar sx, Scalar sy);
|
||||
Transform& preshear(Scalar sx, Scalar sy);
|
||||
|
||||
inline Transform& operator=(const TranslationType& t);
|
||||
inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
|
||||
inline Transform operator*(const TranslationType& t) const;
|
||||
|
||||
inline Transform& operator=(const ScalingType& t);
|
||||
inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); }
|
||||
inline Transform operator*(const ScalingType& s) const;
|
||||
friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
|
||||
{
|
||||
Transform res = t;
|
||||
res.matrix().row(Dim) = t.matrix().row(Dim);
|
||||
res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
|
||||
LinearMatrixType rotation() const;
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
|
||||
|
||||
inline const MatrixType inverse(TransformTraits traits = Affine) const;
|
||||
|
||||
/** \returns a const pointer to the column major internal matrix */
|
||||
const Scalar* data() const { return m_matrix.data(); }
|
||||
/** \returns a non-const pointer to the column major internal matrix */
|
||||
Scalar* data() { return m_matrix.data(); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
|
||||
{ m_matrix = other.matrix().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||
|
||||
#ifdef EIGEN_TRANSFORM_PLUGIN
|
||||
#include EIGEN_TRANSFORM_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,2> Transform2f;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,3> Transform3f;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,2> Transform2d;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,3> Transform3d;
|
||||
|
||||
/**************************
|
||||
*** Optional QT support ***
|
||||
**************************/
|
||||
|
||||
#ifdef EIGEN_QT_SUPPORT
|
||||
/** Initialises \c *this from a QMatrix assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>::Transform(const QMatrix& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/** Set \c *this from a QMatrix assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
0, 0, 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns a QMatrix from \c *this assuming the dimension is 2.
|
||||
*
|
||||
* \warning this convertion might loss data if \c *this is not affine
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2));
|
||||
}
|
||||
|
||||
/** Initialises \c *this from a QTransform assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>::Transform(const QTransform& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/** Set \c *this from a QTransform assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
other.m13(), other.m23(), other.m33();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns a QTransform from \c *this assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
QTransform Transform<Scalar,Dim>::toQTransform(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
*** Procedural API ***
|
||||
*********************/
|
||||
|
||||
/** Applies on the right the non uniform scale transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \sa prescale()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
linear() = (linear() * other.asDiagonal()).lazy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right a uniform scale of a factor \a c to \c *this
|
||||
* and returns a reference to \c *this.
|
||||
* \sa prescale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::scale(Scalar s)
|
||||
{
|
||||
linear() *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the non uniform scale transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \sa scale()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left a uniform scale of a factor \a c to \c *this
|
||||
* and returns a reference to \c *this.
|
||||
* \sa scale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::prescale(Scalar s)
|
||||
{
|
||||
m_matrix.template corner<Dim,HDim>(TopLeft) *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the translation matrix represented by the vector \a other
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
* \sa pretranslate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += linear() * other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the translation matrix represented by the vector \a other
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
* \sa translate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the rotation represented by the rotation \a rotation
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* The template parameter \a RotationType is the type of the rotation which
|
||||
* must be known by ei_toRotationMatrix<>.
|
||||
*
|
||||
* Natively supported types includes:
|
||||
* - any scalar (2D),
|
||||
* - a Dim x Dim matrix expression,
|
||||
* - a Quaternion (3D),
|
||||
* - a AngleAxis (3D)
|
||||
*
|
||||
* This mechanism is easily extendable to support user types such as Euler angles,
|
||||
* or a pair of Quaternion for 4D rotations.
|
||||
*
|
||||
* \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::rotate(const RotationType& rotation)
|
||||
{
|
||||
linear() *= ei_toRotationMatrix<Scalar,Dim>(rotation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the rotation represented by the rotation \a rotation
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* See rotate() for further details.
|
||||
*
|
||||
* \sa rotate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::prerotate(const RotationType& rotation)
|
||||
{
|
||||
m_matrix.template block<Dim,HDim>(0,0) = ei_toRotationMatrix<Scalar,Dim>(rotation)
|
||||
* m_matrix.template block<Dim,HDim>(0,0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the shear transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \warning 2D only.
|
||||
* \sa preshear()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
VectorType tmp = linear().col(0)*sy + linear().col(1);
|
||||
linear() << linear().col(0) + linear().col(1)*sx, tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the shear transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \warning 2D only.
|
||||
* \sa shear()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
*** Scaling, Translation and Rotation compatibility ***
|
||||
******************************************************/
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
|
||||
{
|
||||
linear().setIdentity();
|
||||
translation() = t.vector();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.translate(t.vector());
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s)
|
||||
{
|
||||
m_matrix.setZero();
|
||||
linear().diagonal() = s.coeffs();
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.scale(s.coeffs());
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
|
||||
{
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(r);
|
||||
translation().setZero();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
return res;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** Special functions ***
|
||||
************************/
|
||||
|
||||
/** \returns the rotation part of the transformation
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
typename Transform<Scalar,Dim>::LinearMatrixType
|
||||
Transform<Scalar,Dim>::rotation() const
|
||||
{
|
||||
LinearMatrixType result;
|
||||
computeRotationScaling(&result, (LinearMatrixType*)0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeScalingRotation(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
|
||||
Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, Dim, 1> sv(svd.singularValues());
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling)
|
||||
{
|
||||
scaling->noalias() = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
|
||||
}
|
||||
if(rotation)
|
||||
{
|
||||
LinearMatrixType m(svd.matrixU());
|
||||
m.col(0) /= x;
|
||||
rotation->noalias() = m * svd.matrixV().adjoint();
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
|
||||
Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, Dim, 1> sv(svd.singularValues());
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling)
|
||||
{
|
||||
scaling->noalias() = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
|
||||
}
|
||||
if(rotation)
|
||||
{
|
||||
LinearMatrixType m(svd.matrixU());
|
||||
m.col(0) /= x;
|
||||
rotation->noalias() = m * svd.matrixV().adjoint();
|
||||
}
|
||||
}
|
||||
|
||||
/** Convenient method to set \c *this from a position, orientation and scale
|
||||
* of a 3D object.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
|
||||
{
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
|
||||
linear() *= scale.asDiagonal();
|
||||
translation() = position;
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \nonstableyet
|
||||
*
|
||||
* \returns the inverse transformation matrix according to some given knowledge
|
||||
* on \c *this.
|
||||
*
|
||||
* \param traits allows to optimize the inversion process when the transformion
|
||||
* is known to be not a general transformation. The possible values are:
|
||||
* - Projective if the transformation is not necessarily affine, i.e., if the
|
||||
* last row is not guaranteed to be [0 ... 0 1]
|
||||
* - Affine is the default, the last row is assumed to be [0 ... 0 1]
|
||||
* - Isometry if the transformation is only a concatenations of translations
|
||||
* and rotations.
|
||||
*
|
||||
* \warning unless \a traits is always set to NoShear or NoScaling, this function
|
||||
* requires the generic inverse method of MatrixBase defined in the LU module. If
|
||||
* you forget to include this module, then you will get hard to debug linking errors.
|
||||
*
|
||||
* \sa MatrixBase::inverse()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline const typename Transform<Scalar,Dim>::MatrixType
|
||||
Transform<Scalar,Dim>::inverse(TransformTraits traits) const
|
||||
{
|
||||
if (traits == Projective)
|
||||
{
|
||||
return m_matrix.inverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
MatrixType res;
|
||||
if (traits == Affine)
|
||||
{
|
||||
res.template corner<Dim,Dim>(TopLeft) = linear().inverse();
|
||||
}
|
||||
else if (traits == Isometry)
|
||||
{
|
||||
res.template corner<Dim,Dim>(TopLeft) = linear().transpose();
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Transform::inverse()");
|
||||
}
|
||||
// translation and remaining parts
|
||||
res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation();
|
||||
res.template corner<1,Dim>(BottomLeft).setZero();
|
||||
res.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
*** Specializations of operator* with a MatrixBase ***
|
||||
*****************************************************/
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return tr.matrix() * other; }
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef TransformType ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{
|
||||
TransformType res;
|
||||
res.translation() = tr.translation();
|
||||
res.matrix().row(Dim) = tr.matrix().row(Dim);
|
||||
res.linear() = (tr.linear() * other).lazy();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return tr.matrix() * other; }
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
typedef Matrix<Scalar,Dim,1> ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return ((tr.linear() * other) + tr.translation())
|
||||
* (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
@ -1,184 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Translation
|
||||
*
|
||||
* \brief Represents a translation transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a translation transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Scaling, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Translation
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** corresponding vector type */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** corresponding scaling transformation type */
|
||||
typedef Scaling<Scalar,Dim> ScalingType;
|
||||
/** corresponding affine transformation type */
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_coeffs;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Translation() {}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
ei_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
ei_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the scaling transformation from a vector of scaling coefficients */
|
||||
explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
|
||||
|
||||
const VectorType& vector() const { return m_coeffs; }
|
||||
VectorType& vector() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two translation */
|
||||
inline Translation operator* (const Translation& other) const
|
||||
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||
|
||||
/** Concatenates a translation and a scaling */
|
||||
inline TransformType operator* (const ScalingType& other) const;
|
||||
|
||||
/** Concatenates a translation and a linear transformation */
|
||||
inline TransformType operator* (const LinearMatrixType& linear) const;
|
||||
|
||||
template<typename Derived>
|
||||
inline TransformType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * r.toRotationMatrix(); }
|
||||
|
||||
/** Concatenates a linear transformation and a translation */
|
||||
// its a nightmare to define a templated friend function outside its declaration
|
||||
friend inline TransformType operator* (const LinearMatrixType& linear, const Translation& t)
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear;
|
||||
res.translation() = linear * t.m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Concatenates a translation and an affine transformation */
|
||||
inline TransformType operator* (const TransformType& t) const;
|
||||
|
||||
/** Applies translation to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return m_coeffs + other; }
|
||||
|
||||
/** \returns the inverse translation (opposite) */
|
||||
Translation inverse() const { return Translation(-m_coeffs); }
|
||||
|
||||
Translation& operator=(const Translation& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Translation<float, 2> Translation2f;
|
||||
typedef Translation<double,2> Translation2d;
|
||||
typedef Translation<float, 3> Translation3f;
|
||||
typedef Translation<double,3> Translation3d;
|
||||
//@}
|
||||
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const ScalingType& other) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal() = other.coeffs();
|
||||
res.translation() = m_coeffs;
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const LinearMatrixType& linear) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear;
|
||||
res.translation() = m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const TransformType& t) const
|
||||
{
|
||||
TransformType res = t;
|
||||
res.pretranslate(m_coeffs);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
@ -1,120 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_LU_H
|
||||
#define EIGEN2_LU_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename MatrixType>
|
||||
class LU : public FullPivLU<MatrixType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<int, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> IntRowVectorType;
|
||||
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> IntColVectorType;
|
||||
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> RowVectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> ColVectorType;
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix
|
||||
// so that the product "matrix * kernel = zero" makes sense
|
||||
Dynamic, // we don't know at compile-time the dimension of the kernel
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
|
||||
MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number
|
||||
// of columns of the original matrix
|
||||
> KernelResultType;
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number
|
||||
// of rows of the original matrix
|
||||
Dynamic, // we don't know at compile time the dimension of the image (the rank)
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
|
||||
MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
|
||||
> ImageResultType;
|
||||
|
||||
typedef FullPivLU<MatrixType> Base;
|
||||
|
||||
template<typename T>
|
||||
explicit LU(const T& t) : Base(t), m_originalMatrix(t) {}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->solve(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ResultType>
|
||||
inline void computeInverse(ResultType *result) const
|
||||
{
|
||||
solve(MatrixType::Identity(this->rows(), this->cols()), result);
|
||||
}
|
||||
|
||||
template<typename KernelMatrixType>
|
||||
void computeKernel(KernelMatrixType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->kernel();
|
||||
}
|
||||
|
||||
template<typename ImageMatrixType>
|
||||
void computeImage(ImageMatrixType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->image(m_originalMatrix);
|
||||
}
|
||||
|
||||
const ImageResultType image() const
|
||||
{
|
||||
return static_cast<const Base*>(this)->image(m_originalMatrix);
|
||||
}
|
||||
|
||||
const MatrixType& m_originalMatrix;
|
||||
};
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LU<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::lu() const
|
||||
{
|
||||
return LU<PlainObject>(eval());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LU<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::eigen2_lu() const
|
||||
{
|
||||
return LU<PlainObject>(eval());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_LU_H
|
@ -1,71 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_LAZY_H
|
||||
#define EIGEN_LAZY_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \deprecated it is only used by lazy() which is deprecated
|
||||
*
|
||||
* \returns an expression of *this with added flags
|
||||
*
|
||||
* Example: \include MatrixBase_marked.cpp
|
||||
* Output: \verbinclude MatrixBase_marked.out
|
||||
*
|
||||
* \sa class Flagged, extract(), part()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<unsigned int Added>
|
||||
inline const Flagged<Derived, Added, 0>
|
||||
MatrixBase<Derived>::marked() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \deprecated use MatrixBase::noalias()
|
||||
*
|
||||
* \returns an expression of *this with the EvalBeforeAssigningBit flag removed.
|
||||
*
|
||||
* Example: \include MatrixBase_lazy.cpp
|
||||
* Output: \verbinclude MatrixBase_lazy.out
|
||||
*
|
||||
* \sa class Flagged, marked()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Flagged<Derived, 0, EvalBeforeAssigningBit>
|
||||
MatrixBase<Derived>::lazy() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
/** \internal
|
||||
* Overloaded to perform an efficient C += (A*B).lazy() */
|
||||
template<typename Derived>
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other)
|
||||
{
|
||||
other._expression().derived().addTo(derived()); return derived();
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* Overloaded to perform an efficient C -= (A*B).lazy() */
|
||||
template<typename Derived>
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other)
|
||||
{
|
||||
other._expression().derived().subTo(derived()); return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_LAZY_H
|
@ -1,170 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_LEASTSQUARES_H
|
||||
#define EIGEN2_LEASTSQUARES_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \leastsquares_module
|
||||
*
|
||||
* For a set of points, this function tries to express
|
||||
* one of the coords as a linear (affine) function of the other coords.
|
||||
*
|
||||
* This is best explained by an example. This function works in full
|
||||
* generality, for points in a space of arbitrary dimension, and also over
|
||||
* the complex numbers, but for this example we will work in dimension 3
|
||||
* over the real numbers (doubles).
|
||||
*
|
||||
* So let us work with the following set of 5 points given by their
|
||||
* \f$(x,y,z)\f$ coordinates:
|
||||
* @code
|
||||
Vector3d points[5];
|
||||
points[0] = Vector3d( 3.02, 6.89, -4.32 );
|
||||
points[1] = Vector3d( 2.01, 5.39, -3.79 );
|
||||
points[2] = Vector3d( 2.41, 6.01, -4.01 );
|
||||
points[3] = Vector3d( 2.09, 5.55, -3.86 );
|
||||
points[4] = Vector3d( 2.58, 6.32, -4.10 );
|
||||
* @endcode
|
||||
* Suppose that we want to express the second coordinate (\f$y\f$) as a linear
|
||||
* expression in \f$x\f$ and \f$z\f$, that is,
|
||||
* \f[ y=ax+bz+c \f]
|
||||
* for some constants \f$a,b,c\f$. Thus, we want to find the best possible
|
||||
* constants \f$a,b,c\f$ so that the plane of equation \f$y=ax+bz+c\f$ fits
|
||||
* best the five above points. To do that, call this function as follows:
|
||||
* @code
|
||||
Vector3d coeffs; // will store the coefficients a, b, c
|
||||
linearRegression(
|
||||
5,
|
||||
&points,
|
||||
&coeffs,
|
||||
1 // the coord to express as a function of
|
||||
// the other ones. 0 means x, 1 means y, 2 means z.
|
||||
);
|
||||
* @endcode
|
||||
* Now the vector \a coeffs is approximately
|
||||
* \f$( 0.495 , -1.927 , -2.906 )\f$.
|
||||
* Thus, we get \f$a=0.495, b = -1.927, c = -2.906\f$. Let us check for
|
||||
* instance how near points[0] is from the plane of equation \f$y=ax+bz+c\f$.
|
||||
* Looking at the coords of points[0], we see that:
|
||||
* \f[ax+bz+c = 0.495 * 3.02 + (-1.927) * (-4.32) + (-2.906) = 6.91.\f]
|
||||
* On the other hand, we have \f$y=6.89\f$. We see that the values
|
||||
* \f$6.91\f$ and \f$6.89\f$
|
||||
* are near, so points[0] is very near the plane of equation \f$y=ax+bz+c\f$.
|
||||
*
|
||||
* Let's now describe precisely the parameters:
|
||||
* @param numPoints the number of points
|
||||
* @param points the array of pointers to the points on which to perform the linear regression
|
||||
* @param result pointer to the vector in which to store the result.
|
||||
This vector must be of the same type and size as the
|
||||
data points. The meaning of its coords is as follows.
|
||||
For brevity, let \f$n=Size\f$,
|
||||
\f$r_i=result[i]\f$,
|
||||
and \f$f=funcOfOthers\f$. Denote by
|
||||
\f$x_0,\ldots,x_{n-1}\f$
|
||||
the n coordinates in the n-dimensional space.
|
||||
Then the resulting equation is:
|
||||
\f[ x_f = r_0 x_0 + \cdots + r_{f-1}x_{f-1}
|
||||
+ r_{f+1}x_{f+1} + \cdots + r_{n-1}x_{n-1} + r_n. \f]
|
||||
* @param funcOfOthers Determines which coord to express as a function of the
|
||||
others. Coords are numbered starting from 0, so that a
|
||||
value of 0 means \f$x\f$, 1 means \f$y\f$,
|
||||
2 means \f$z\f$, ...
|
||||
*
|
||||
* \sa fitHyperplane()
|
||||
*/
|
||||
template<typename VectorType>
|
||||
void linearRegression(int numPoints,
|
||||
VectorType **points,
|
||||
VectorType *result,
|
||||
int funcOfOthers )
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
typedef Hyperplane<Scalar, VectorType::SizeAtCompileTime> HyperplaneType;
|
||||
const int size = points[0]->size();
|
||||
result->resize(size);
|
||||
HyperplaneType h(size);
|
||||
fitHyperplane(numPoints, points, &h);
|
||||
for(int i = 0; i < funcOfOthers; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i] / h.coeffs()[funcOfOthers];
|
||||
for(int i = funcOfOthers; i < size; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i+1] / h.coeffs()[funcOfOthers];
|
||||
}
|
||||
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \leastsquares_module
|
||||
*
|
||||
* This function is quite similar to linearRegression(), so we refer to the
|
||||
* documentation of this function and only list here the differences.
|
||||
*
|
||||
* The main difference from linearRegression() is that this function doesn't
|
||||
* take a \a funcOfOthers argument. Instead, it finds a general equation
|
||||
* of the form
|
||||
* \f[ r_0 x_0 + \cdots + r_{n-1}x_{n-1} + r_n = 0, \f]
|
||||
* where \f$n=Size\f$, \f$r_i=retCoefficients[i]\f$, and we denote by
|
||||
* \f$x_0,\ldots,x_{n-1}\f$ the n coordinates in the n-dimensional space.
|
||||
*
|
||||
* Thus, the vector \a retCoefficients has size \f$n+1\f$, which is another
|
||||
* difference from linearRegression().
|
||||
*
|
||||
* In practice, this function performs an hyper-plane fit in a total least square sense
|
||||
* via the following steps:
|
||||
* 1 - center the data to the mean
|
||||
* 2 - compute the covariance matrix
|
||||
* 3 - pick the eigenvector corresponding to the smallest eigenvalue of the covariance matrix
|
||||
* The ratio of the smallest eigenvalue and the second one gives us a hint about the relevance
|
||||
* of the solution. This value is optionally returned in \a soundness.
|
||||
*
|
||||
* \sa linearRegression()
|
||||
*/
|
||||
template<typename VectorType, typename HyperplaneType>
|
||||
void fitHyperplane(int numPoints,
|
||||
VectorType **points,
|
||||
HyperplaneType *result,
|
||||
typename NumTraits<typename VectorType::Scalar>::Real* soundness = 0)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
typedef Matrix<Scalar,VectorType::SizeAtCompileTime,VectorType::SizeAtCompileTime> CovMatrixType;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType)
|
||||
ei_assert(numPoints >= 1);
|
||||
int size = points[0]->size();
|
||||
ei_assert(size+1 == result->coeffs().size());
|
||||
|
||||
// compute the mean of the data
|
||||
VectorType mean = VectorType::Zero(size);
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
mean += *(points[i]);
|
||||
mean /= numPoints;
|
||||
|
||||
// compute the covariance matrix
|
||||
CovMatrixType covMat = CovMatrixType::Zero(size, size);
|
||||
VectorType remean = VectorType::Zero(size);
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
{
|
||||
VectorType diff = (*(points[i]) - mean).conjugate();
|
||||
covMat += diff * diff.adjoint();
|
||||
}
|
||||
|
||||
// now we just have to pick the eigen vector with smallest eigen value
|
||||
SelfAdjointEigenSolver<CovMatrixType> eig(covMat);
|
||||
result->normal() = eig.eigenvectors().col(0);
|
||||
if (soundness)
|
||||
*soundness = eig.eigenvalues().coeff(0)/eig.eigenvalues().coeff(1);
|
||||
|
||||
// let's compute the constant coefficient such that the
|
||||
// plane pass trough the mean point:
|
||||
result->offset() = - (result->normal().cwise()* mean).sum();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_LEASTSQUARES_H
|
@ -1,20 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_MACROS_H
|
||||
#define EIGEN2_MACROS_H
|
||||
|
||||
#define ei_assert eigen_assert
|
||||
#define ei_internal_assert eigen_internal_assert
|
||||
|
||||
#define EIGEN_ALIGN_128 EIGEN_ALIGN16
|
||||
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT EIGEN_ALIGN_STATICALLY
|
||||
|
||||
#endif // EIGEN2_MACROS_H
|
@ -1,57 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_MATH_FUNCTIONS_H
|
||||
#define EIGEN2_MATH_FUNCTIONS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return numext::real(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return numext::imag(x); }
|
||||
template<typename T> inline T ei_conj(const T& x) { return numext::conj(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { using std::abs; return abs(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return numext::abs2(x); }
|
||||
template<typename T> inline T ei_sqrt(const T& x) { using std::sqrt; return sqrt(x); }
|
||||
template<typename T> inline T ei_exp (const T& x) { using std::exp; return exp(x); }
|
||||
template<typename T> inline T ei_log (const T& x) { using std::log; return log(x); }
|
||||
template<typename T> inline T ei_sin (const T& x) { using std::sin; return sin(x); }
|
||||
template<typename T> inline T ei_cos (const T& x) { using std::cos; return cos(x); }
|
||||
template<typename T> inline T ei_atan2(const T& x,const T& y) { using std::atan2; return atan2(x,y); }
|
||||
template<typename T> inline T ei_pow (const T& x,const T& y) { return numext::pow(x,y); }
|
||||
template<typename T> inline T ei_random () { return internal::random<T>(); }
|
||||
template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
|
||||
|
||||
template<typename T> inline T precision () { return NumTraits<T>::dummy_precision(); }
|
||||
template<typename T> inline T machine_epsilon () { return NumTraits<T>::epsilon(); }
|
||||
|
||||
|
||||
template<typename Scalar, typename OtherScalar>
|
||||
inline bool ei_isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isMuchSmallerThan(x, y, precision);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline bool ei_isApprox(const Scalar& x, const Scalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isApprox(x, y, precision);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline bool ei_isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isApproxOrLessThan(x, y, precision);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_MATH_FUNCTIONS_H
|
@ -1,45 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_MEMORY_H
|
||||
#define EIGEN2_MEMORY_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
inline void* ei_aligned_malloc(size_t size) { return internal::aligned_malloc(size); }
|
||||
inline void ei_aligned_free(void *ptr) { internal::aligned_free(ptr); }
|
||||
inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size) { return internal::aligned_realloc(ptr, new_size, old_size); }
|
||||
inline void* ei_handmade_aligned_malloc(size_t size) { return internal::handmade_aligned_malloc(size); }
|
||||
inline void ei_handmade_aligned_free(void *ptr) { internal::handmade_aligned_free(ptr); }
|
||||
|
||||
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
|
||||
{
|
||||
return internal::conditional_aligned_malloc<Align>(size);
|
||||
}
|
||||
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
|
||||
{
|
||||
internal::conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
template<bool Align> inline void* ei_conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
|
||||
{
|
||||
return internal::conditional_aligned_realloc<Align>(ptr, new_size, old_size);
|
||||
}
|
||||
|
||||
template<typename T> inline T* ei_aligned_new(size_t size)
|
||||
{
|
||||
return internal::aligned_new<T>(size);
|
||||
}
|
||||
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
return internal::aligned_delete(ptr, size);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_MACROS_H
|
@ -1,75 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_META_H
|
||||
#define EIGEN2_META_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T>
|
||||
struct ei_traits : internal::traits<T>
|
||||
{};
|
||||
|
||||
struct ei_meta_true { enum { ret = 1 }; };
|
||||
struct ei_meta_false { enum { ret = 0 }; };
|
||||
|
||||
template<bool Condition, typename Then, typename Else>
|
||||
struct ei_meta_if { typedef Then ret; };
|
||||
|
||||
template<typename Then, typename Else>
|
||||
struct ei_meta_if <false, Then, Else> { typedef Else ret; };
|
||||
|
||||
template<typename T, typename U> struct ei_is_same_type { enum { ret = 0 }; };
|
||||
template<typename T> struct ei_is_same_type<T,T> { enum { ret = 1 }; };
|
||||
|
||||
template<typename T> struct ei_unref { typedef T type; };
|
||||
template<typename T> struct ei_unref<T&> { typedef T type; };
|
||||
|
||||
template<typename T> struct ei_unpointer { typedef T type; };
|
||||
template<typename T> struct ei_unpointer<T*> { typedef T type; };
|
||||
template<typename T> struct ei_unpointer<T*const> { typedef T type; };
|
||||
|
||||
template<typename T> struct ei_unconst { typedef T type; };
|
||||
template<typename T> struct ei_unconst<const T> { typedef T type; };
|
||||
template<typename T> struct ei_unconst<T const &> { typedef T & type; };
|
||||
template<typename T> struct ei_unconst<T const *> { typedef T * type; };
|
||||
|
||||
template<typename T> struct ei_cleantype { typedef T type; };
|
||||
template<typename T> struct ei_cleantype<const T> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<const T&> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<T&> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<const T*> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleantype<T>::type type; };
|
||||
|
||||
/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
|
||||
* Usage example: \code ei_meta_sqrt<1023>::ret \endcode
|
||||
*/
|
||||
template<int Y,
|
||||
int InfX = 0,
|
||||
int SupX = ((Y==1) ? 1 : Y/2),
|
||||
bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
|
||||
// use ?: instead of || just to shut up a stupid gcc 4.3 warning
|
||||
class ei_meta_sqrt
|
||||
{
|
||||
enum {
|
||||
MidX = (InfX+SupX)/2,
|
||||
TakeInf = MidX*MidX > Y ? 1 : 0,
|
||||
NewInf = int(TakeInf) ? InfX : int(MidX),
|
||||
NewSup = int(TakeInf) ? int(MidX) : SupX
|
||||
};
|
||||
public:
|
||||
enum { ret = ei_meta_sqrt<Y,NewInf,NewSup>::ret };
|
||||
};
|
||||
|
||||
template<int Y, int InfX, int SupX>
|
||||
class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_META_H
|
@ -1,117 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_MINOR_H
|
||||
#define EIGEN_MINOR_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/**
|
||||
* \class Minor
|
||||
*
|
||||
* \brief Expression of a minor
|
||||
*
|
||||
* \param MatrixType the type of the object in which we are taking a minor
|
||||
*
|
||||
* This class represents an expression of a minor. It is the return
|
||||
* type of MatrixBase::minor() and most of the time this is the only way it
|
||||
* is used.
|
||||
*
|
||||
* \sa MatrixBase::minor()
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType>
|
||||
struct traits<Minor<MatrixType> >
|
||||
: traits<MatrixType>
|
||||
{
|
||||
typedef typename nested<MatrixType>::type MatrixTypeNested;
|
||||
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
typedef typename MatrixType::StorageKind StorageKind;
|
||||
enum {
|
||||
RowsAtCompileTime = (MatrixType::RowsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::RowsAtCompileTime) - 1 : Dynamic,
|
||||
ColsAtCompileTime = (MatrixType::ColsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::ColsAtCompileTime) - 1 : Dynamic,
|
||||
MaxRowsAtCompileTime = (MatrixType::MaxRowsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::MaxRowsAtCompileTime) - 1 : Dynamic,
|
||||
MaxColsAtCompileTime = (MatrixType::MaxColsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::MaxColsAtCompileTime) - 1 : Dynamic,
|
||||
Flags = _MatrixTypeNested::Flags & (HereditaryBits | LvalueBit),
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost // minor is used typically on tiny matrices,
|
||||
// where loops are unrolled and the 'if' evaluates at compile time
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename MatrixType> class Minor
|
||||
: public MatrixBase<Minor<MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MatrixBase<Minor> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Minor)
|
||||
|
||||
inline Minor(const MatrixType& matrix,
|
||||
Index row, Index col)
|
||||
: m_matrix(matrix), m_row(row), m_col(col)
|
||||
{
|
||||
eigen_assert(row >= 0 && row < matrix.rows()
|
||||
&& col >= 0 && col < matrix.cols());
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Minor)
|
||||
|
||||
inline Index rows() const { return m_matrix.rows() - 1; }
|
||||
inline Index cols() const { return m_matrix.cols() - 1; }
|
||||
|
||||
inline Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(row + (row >= m_row), col + (col >= m_col));
|
||||
}
|
||||
|
||||
inline const Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
return m_matrix.coeff(row + (row >= m_row), col + (col >= m_col));
|
||||
}
|
||||
|
||||
protected:
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
const Index m_row, m_col;
|
||||
};
|
||||
|
||||
/**
|
||||
* \return an expression of the (\a row, \a col)-minor of *this,
|
||||
* i.e. an expression constructed from *this by removing the specified
|
||||
* row and column.
|
||||
*
|
||||
* Example: \include MatrixBase_minor.cpp
|
||||
* Output: \verbinclude MatrixBase_minor.out
|
||||
*
|
||||
* \sa class Minor
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Minor<Derived>
|
||||
MatrixBase<Derived>::minor(Index row, Index col)
|
||||
{
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the const version of minor(). */
|
||||
template<typename Derived>
|
||||
inline const Minor<Derived>
|
||||
MatrixBase<Derived>::minor(Index row, Index col) const
|
||||
{
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_MINOR_H
|
@ -1,67 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_QR_H
|
||||
#define EIGEN2_QR_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename MatrixType>
|
||||
class QR : public HouseholderQR<MatrixType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef HouseholderQR<MatrixType> Base;
|
||||
typedef Block<const MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType;
|
||||
|
||||
QR() : Base() {}
|
||||
|
||||
template<typename T>
|
||||
explicit QR(const T& t) : Base(t) {}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->solve(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
MatrixType matrixQ(void) const {
|
||||
MatrixType ret = MatrixType::Identity(this->rows(), this->cols());
|
||||
ret = this->householderQ() * ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isFullRank() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
const TriangularView<MatrixRBlockType, UpperTriangular>
|
||||
matrixR(void) const
|
||||
{
|
||||
int cols = this->cols();
|
||||
return MatrixRBlockType(this->matrixQR(), 0, 0, cols, cols).template triangularView<UpperTriangular>();
|
||||
}
|
||||
};
|
||||
|
||||
/** \return the QR decomposition of \c *this.
|
||||
*
|
||||
* \sa class QR
|
||||
*/
|
||||
template<typename Derived>
|
||||
const QR<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::qr() const
|
||||
{
|
||||
return QR<PlainObject>(eval());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_QR_H
|
@ -1,637 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_SVD_H
|
||||
#define EIGEN2_SVD_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \ingroup SVD_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class SVD
|
||||
*
|
||||
* \brief Standard SVD decomposition of a matrix and associated features
|
||||
*
|
||||
* \param MatrixType the type of the matrix of which we are computing the SVD decomposition
|
||||
*
|
||||
* This class performs a standard SVD decomposition of a real matrix A of size \c M x \c N
|
||||
* with \c M \>= \c N.
|
||||
*
|
||||
*
|
||||
* \sa MatrixBase::SVD()
|
||||
*/
|
||||
template<typename MatrixType> class SVD
|
||||
{
|
||||
private:
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
|
||||
enum {
|
||||
PacketSize = internal::packet_traits<Scalar>::size,
|
||||
AlignmentMask = int(PacketSize)-1,
|
||||
MinSize = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
|
||||
};
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVector;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> RowVector;
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MinSize> MatrixUType;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixVType;
|
||||
typedef Matrix<Scalar, MinSize, 1> SingularValuesType;
|
||||
|
||||
public:
|
||||
|
||||
SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
|
||||
|
||||
SVD(const MatrixType& matrix)
|
||||
: m_matU(matrix.rows(), (std::min)(matrix.rows(), matrix.cols())),
|
||||
m_matV(matrix.cols(),matrix.cols()),
|
||||
m_sigma((std::min)(matrix.rows(),matrix.cols()))
|
||||
{
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived> &b, ResultType* result) const;
|
||||
|
||||
const MatrixUType& matrixU() const { return m_matU; }
|
||||
const SingularValuesType& singularValues() const { return m_sigma; }
|
||||
const MatrixVType& matrixV() const { return m_matV; }
|
||||
|
||||
void compute(const MatrixType& matrix);
|
||||
SVD& sort();
|
||||
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void computeUnitaryPositive(UnitaryType *unitary, PositiveType *positive) const;
|
||||
template<typename PositiveType, typename UnitaryType>
|
||||
void computePositiveUnitary(PositiveType *positive, UnitaryType *unitary) const;
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void computeRotationScaling(RotationType *unitary, ScalingType *positive) const;
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void computeScalingRotation(ScalingType *positive, RotationType *unitary) const;
|
||||
|
||||
protected:
|
||||
/** \internal */
|
||||
MatrixUType m_matU;
|
||||
/** \internal */
|
||||
MatrixVType m_matV;
|
||||
/** \internal */
|
||||
SingularValuesType m_sigma;
|
||||
};
|
||||
|
||||
/** Computes / recomputes the SVD decomposition A = U S V^* of \a matrix
|
||||
*
|
||||
* \note this code has been adapted from JAMA (public domain)
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
void SVD<MatrixType>::compute(const MatrixType& matrix)
|
||||
{
|
||||
const int m = matrix.rows();
|
||||
const int n = matrix.cols();
|
||||
const int nu = (std::min)(m,n);
|
||||
ei_assert(m>=n && "In Eigen 2.0, SVD only works for MxN matrices with M>=N. Sorry!");
|
||||
ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices");
|
||||
|
||||
m_matU.resize(m, nu);
|
||||
m_matU.setZero();
|
||||
m_sigma.resize((std::min)(m,n));
|
||||
m_matV.resize(n,n);
|
||||
|
||||
RowVector e(n);
|
||||
ColVector work(m);
|
||||
MatrixType matA(matrix);
|
||||
const bool wantu = true;
|
||||
const bool wantv = true;
|
||||
int i=0, j=0, k=0;
|
||||
|
||||
// Reduce A to bidiagonal form, storing the diagonal elements
|
||||
// in s and the super-diagonal elements in e.
|
||||
int nct = (std::min)(m-1,n);
|
||||
int nrt = (std::max)(0,(std::min)(n-2,m));
|
||||
for (k = 0; k < (std::max)(nct,nrt); ++k)
|
||||
{
|
||||
if (k < nct)
|
||||
{
|
||||
// Compute the transformation for the k-th column and
|
||||
// place the k-th diagonal in m_sigma[k].
|
||||
m_sigma[k] = matA.col(k).end(m-k).norm();
|
||||
if (m_sigma[k] != 0.0) // FIXME
|
||||
{
|
||||
if (matA(k,k) < 0.0)
|
||||
m_sigma[k] = -m_sigma[k];
|
||||
matA.col(k).end(m-k) /= m_sigma[k];
|
||||
matA(k,k) += 1.0;
|
||||
}
|
||||
m_sigma[k] = -m_sigma[k];
|
||||
}
|
||||
|
||||
for (j = k+1; j < n; ++j)
|
||||
{
|
||||
if ((k < nct) && (m_sigma[k] != 0.0))
|
||||
{
|
||||
// Apply the transformation.
|
||||
Scalar t = matA.col(k).end(m-k).eigen2_dot(matA.col(j).end(m-k)); // FIXME dot product or cwise prod + .sum() ??
|
||||
t = -t/matA(k,k);
|
||||
matA.col(j).end(m-k) += t * matA.col(k).end(m-k);
|
||||
}
|
||||
|
||||
// Place the k-th row of A into e for the
|
||||
// subsequent calculation of the row transformation.
|
||||
e[j] = matA(k,j);
|
||||
}
|
||||
|
||||
// Place the transformation in U for subsequent back multiplication.
|
||||
if (wantu & (k < nct))
|
||||
m_matU.col(k).end(m-k) = matA.col(k).end(m-k);
|
||||
|
||||
if (k < nrt)
|
||||
{
|
||||
// Compute the k-th row transformation and place the
|
||||
// k-th super-diagonal in e[k].
|
||||
e[k] = e.end(n-k-1).norm();
|
||||
if (e[k] != 0.0)
|
||||
{
|
||||
if (e[k+1] < 0.0)
|
||||
e[k] = -e[k];
|
||||
e.end(n-k-1) /= e[k];
|
||||
e[k+1] += 1.0;
|
||||
}
|
||||
e[k] = -e[k];
|
||||
if ((k+1 < m) & (e[k] != 0.0))
|
||||
{
|
||||
// Apply the transformation.
|
||||
work.end(m-k-1) = matA.corner(BottomRight,m-k-1,n-k-1) * e.end(n-k-1);
|
||||
for (j = k+1; j < n; ++j)
|
||||
matA.col(j).end(m-k-1) += (-e[j]/e[k+1]) * work.end(m-k-1);
|
||||
}
|
||||
|
||||
// Place the transformation in V for subsequent back multiplication.
|
||||
if (wantv)
|
||||
m_matV.col(k).end(n-k-1) = e.end(n-k-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set up the final bidiagonal matrix or order p.
|
||||
int p = (std::min)(n,m+1);
|
||||
if (nct < n)
|
||||
m_sigma[nct] = matA(nct,nct);
|
||||
if (m < p)
|
||||
m_sigma[p-1] = 0.0;
|
||||
if (nrt+1 < p)
|
||||
e[nrt] = matA(nrt,p-1);
|
||||
e[p-1] = 0.0;
|
||||
|
||||
// If required, generate U.
|
||||
if (wantu)
|
||||
{
|
||||
for (j = nct; j < nu; ++j)
|
||||
{
|
||||
m_matU.col(j).setZero();
|
||||
m_matU(j,j) = 1.0;
|
||||
}
|
||||
for (k = nct-1; k >= 0; k--)
|
||||
{
|
||||
if (m_sigma[k] != 0.0)
|
||||
{
|
||||
for (j = k+1; j < nu; ++j)
|
||||
{
|
||||
Scalar t = m_matU.col(k).end(m-k).eigen2_dot(m_matU.col(j).end(m-k)); // FIXME is it really a dot product we want ?
|
||||
t = -t/m_matU(k,k);
|
||||
m_matU.col(j).end(m-k) += t * m_matU.col(k).end(m-k);
|
||||
}
|
||||
m_matU.col(k).end(m-k) = - m_matU.col(k).end(m-k);
|
||||
m_matU(k,k) = Scalar(1) + m_matU(k,k);
|
||||
if (k-1>0)
|
||||
m_matU.col(k).start(k-1).setZero();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_matU.col(k).setZero();
|
||||
m_matU(k,k) = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If required, generate V.
|
||||
if (wantv)
|
||||
{
|
||||
for (k = n-1; k >= 0; k--)
|
||||
{
|
||||
if ((k < nrt) & (e[k] != 0.0))
|
||||
{
|
||||
for (j = k+1; j < nu; ++j)
|
||||
{
|
||||
Scalar t = m_matV.col(k).end(n-k-1).eigen2_dot(m_matV.col(j).end(n-k-1)); // FIXME is it really a dot product we want ?
|
||||
t = -t/m_matV(k+1,k);
|
||||
m_matV.col(j).end(n-k-1) += t * m_matV.col(k).end(n-k-1);
|
||||
}
|
||||
}
|
||||
m_matV.col(k).setZero();
|
||||
m_matV(k,k) = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Main iteration loop for the singular values.
|
||||
int pp = p-1;
|
||||
int iter = 0;
|
||||
Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
|
||||
while (p > 0)
|
||||
{
|
||||
int k=0;
|
||||
int kase=0;
|
||||
|
||||
// Here is where a test for too many iterations would go.
|
||||
|
||||
// This section of the program inspects for
|
||||
// negligible elements in the s and e arrays. On
|
||||
// completion the variables kase and k are set as follows.
|
||||
|
||||
// kase = 1 if s(p) and e[k-1] are negligible and k<p
|
||||
// kase = 2 if s(k) is negligible and k<p
|
||||
// kase = 3 if e[k-1] is negligible, k<p, and
|
||||
// s(k), ..., s(p) are not negligible (qr step).
|
||||
// kase = 4 if e(p-1) is negligible (convergence).
|
||||
|
||||
for (k = p-2; k >= -1; --k)
|
||||
{
|
||||
if (k == -1)
|
||||
break;
|
||||
if (ei_abs(e[k]) <= eps*(ei_abs(m_sigma[k]) + ei_abs(m_sigma[k+1])))
|
||||
{
|
||||
e[k] = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == p-2)
|
||||
{
|
||||
kase = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ks;
|
||||
for (ks = p-1; ks >= k; --ks)
|
||||
{
|
||||
if (ks == k)
|
||||
break;
|
||||
Scalar t = (ks != p ? ei_abs(e[ks]) : Scalar(0)) + (ks != k+1 ? ei_abs(e[ks-1]) : Scalar(0));
|
||||
if (ei_abs(m_sigma[ks]) <= eps*t)
|
||||
{
|
||||
m_sigma[ks] = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ks == k)
|
||||
{
|
||||
kase = 3;
|
||||
}
|
||||
else if (ks == p-1)
|
||||
{
|
||||
kase = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
kase = 2;
|
||||
k = ks;
|
||||
}
|
||||
}
|
||||
++k;
|
||||
|
||||
// Perform the task indicated by kase.
|
||||
switch (kase)
|
||||
{
|
||||
|
||||
// Deflate negligible s(p).
|
||||
case 1:
|
||||
{
|
||||
Scalar f(e[p-2]);
|
||||
e[p-2] = 0.0;
|
||||
for (j = p-2; j >= k; --j)
|
||||
{
|
||||
Scalar t(numext::hypot(m_sigma[j],f));
|
||||
Scalar cs(m_sigma[j]/t);
|
||||
Scalar sn(f/t);
|
||||
m_sigma[j] = t;
|
||||
if (j != k)
|
||||
{
|
||||
f = -sn*e[j-1];
|
||||
e[j-1] = cs*e[j-1];
|
||||
}
|
||||
if (wantv)
|
||||
{
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
t = cs*m_matV(i,j) + sn*m_matV(i,p-1);
|
||||
m_matV(i,p-1) = -sn*m_matV(i,j) + cs*m_matV(i,p-1);
|
||||
m_matV(i,j) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Split at negligible s(k).
|
||||
case 2:
|
||||
{
|
||||
Scalar f(e[k-1]);
|
||||
e[k-1] = 0.0;
|
||||
for (j = k; j < p; ++j)
|
||||
{
|
||||
Scalar t(numext::hypot(m_sigma[j],f));
|
||||
Scalar cs( m_sigma[j]/t);
|
||||
Scalar sn(f/t);
|
||||
m_sigma[j] = t;
|
||||
f = -sn*e[j];
|
||||
e[j] = cs*e[j];
|
||||
if (wantu)
|
||||
{
|
||||
for (i = 0; i < m; ++i)
|
||||
{
|
||||
t = cs*m_matU(i,j) + sn*m_matU(i,k-1);
|
||||
m_matU(i,k-1) = -sn*m_matU(i,j) + cs*m_matU(i,k-1);
|
||||
m_matU(i,j) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Perform one qr step.
|
||||
case 3:
|
||||
{
|
||||
// Calculate the shift.
|
||||
Scalar scale = (std::max)((std::max)((std::max)((std::max)(
|
||||
ei_abs(m_sigma[p-1]),ei_abs(m_sigma[p-2])),ei_abs(e[p-2])),
|
||||
ei_abs(m_sigma[k])),ei_abs(e[k]));
|
||||
Scalar sp = m_sigma[p-1]/scale;
|
||||
Scalar spm1 = m_sigma[p-2]/scale;
|
||||
Scalar epm1 = e[p-2]/scale;
|
||||
Scalar sk = m_sigma[k]/scale;
|
||||
Scalar ek = e[k]/scale;
|
||||
Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/Scalar(2);
|
||||
Scalar c = (sp*epm1)*(sp*epm1);
|
||||
Scalar shift(0);
|
||||
if ((b != 0.0) || (c != 0.0))
|
||||
{
|
||||
shift = ei_sqrt(b*b + c);
|
||||
if (b < 0.0)
|
||||
shift = -shift;
|
||||
shift = c/(b + shift);
|
||||
}
|
||||
Scalar f = (sk + sp)*(sk - sp) + shift;
|
||||
Scalar g = sk*ek;
|
||||
|
||||
// Chase zeros.
|
||||
|
||||
for (j = k; j < p-1; ++j)
|
||||
{
|
||||
Scalar t = numext::hypot(f,g);
|
||||
Scalar cs = f/t;
|
||||
Scalar sn = g/t;
|
||||
if (j != k)
|
||||
e[j-1] = t;
|
||||
f = cs*m_sigma[j] + sn*e[j];
|
||||
e[j] = cs*e[j] - sn*m_sigma[j];
|
||||
g = sn*m_sigma[j+1];
|
||||
m_sigma[j+1] = cs*m_sigma[j+1];
|
||||
if (wantv)
|
||||
{
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
t = cs*m_matV(i,j) + sn*m_matV(i,j+1);
|
||||
m_matV(i,j+1) = -sn*m_matV(i,j) + cs*m_matV(i,j+1);
|
||||
m_matV(i,j) = t;
|
||||
}
|
||||
}
|
||||
t = numext::hypot(f,g);
|
||||
cs = f/t;
|
||||
sn = g/t;
|
||||
m_sigma[j] = t;
|
||||
f = cs*e[j] + sn*m_sigma[j+1];
|
||||
m_sigma[j+1] = -sn*e[j] + cs*m_sigma[j+1];
|
||||
g = sn*e[j+1];
|
||||
e[j+1] = cs*e[j+1];
|
||||
if (wantu && (j < m-1))
|
||||
{
|
||||
for (i = 0; i < m; ++i)
|
||||
{
|
||||
t = cs*m_matU(i,j) + sn*m_matU(i,j+1);
|
||||
m_matU(i,j+1) = -sn*m_matU(i,j) + cs*m_matU(i,j+1);
|
||||
m_matU(i,j) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
e[p-2] = f;
|
||||
iter = iter + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
// Convergence.
|
||||
case 4:
|
||||
{
|
||||
// Make the singular values positive.
|
||||
if (m_sigma[k] <= 0.0)
|
||||
{
|
||||
m_sigma[k] = m_sigma[k] < Scalar(0) ? -m_sigma[k] : Scalar(0);
|
||||
if (wantv)
|
||||
m_matV.col(k).start(pp+1) = -m_matV.col(k).start(pp+1);
|
||||
}
|
||||
|
||||
// Order the singular values.
|
||||
while (k < pp)
|
||||
{
|
||||
if (m_sigma[k] >= m_sigma[k+1])
|
||||
break;
|
||||
Scalar t = m_sigma[k];
|
||||
m_sigma[k] = m_sigma[k+1];
|
||||
m_sigma[k+1] = t;
|
||||
if (wantv && (k < n-1))
|
||||
m_matV.col(k).swap(m_matV.col(k+1));
|
||||
if (wantu && (k < m-1))
|
||||
m_matU.col(k).swap(m_matU.col(k+1));
|
||||
++k;
|
||||
}
|
||||
iter = 0;
|
||||
p--;
|
||||
}
|
||||
break;
|
||||
} // end big switch
|
||||
} // end iterations
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
SVD<MatrixType>& SVD<MatrixType>::sort()
|
||||
{
|
||||
int mu = m_matU.rows();
|
||||
int mv = m_matV.rows();
|
||||
int n = m_matU.cols();
|
||||
|
||||
for (int i=0; i<n; ++i)
|
||||
{
|
||||
int k = i;
|
||||
Scalar p = m_sigma.coeff(i);
|
||||
|
||||
for (int j=i+1; j<n; ++j)
|
||||
{
|
||||
if (m_sigma.coeff(j) > p)
|
||||
{
|
||||
k = j;
|
||||
p = m_sigma.coeff(j);
|
||||
}
|
||||
}
|
||||
if (k != i)
|
||||
{
|
||||
m_sigma.coeffRef(k) = m_sigma.coeff(i); // i.e.
|
||||
m_sigma.coeffRef(i) = p; // swaps the i-th and the k-th elements
|
||||
|
||||
int j = mu;
|
||||
for(int s=0; j!=0; ++s, --j)
|
||||
std::swap(m_matU.coeffRef(s,i), m_matU.coeffRef(s,k));
|
||||
|
||||
j = mv;
|
||||
for (int s=0; j!=0; ++s, --j)
|
||||
std::swap(m_matV.coeffRef(s,i), m_matV.coeffRef(s,k));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the solution of \f$ A x = b \f$ using the current SVD decomposition of A.
|
||||
* The parts of the solution corresponding to zero singular values are ignored.
|
||||
*
|
||||
* \sa MatrixBase::svd(), LU::solve(), LLT::solve()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool SVD<MatrixType>::solve(const MatrixBase<OtherDerived> &b, ResultType* result) const
|
||||
{
|
||||
ei_assert(b.rows() == m_matU.rows());
|
||||
|
||||
Scalar maxVal = m_sigma.cwise().abs().maxCoeff();
|
||||
for (int j=0; j<b.cols(); ++j)
|
||||
{
|
||||
Matrix<Scalar,MatrixUType::RowsAtCompileTime,1> aux = m_matU.transpose() * b.col(j);
|
||||
|
||||
for (int i = 0; i <m_matU.cols(); ++i)
|
||||
{
|
||||
Scalar si = m_sigma.coeff(i);
|
||||
if (ei_isMuchSmallerThan(ei_abs(si),maxVal))
|
||||
aux.coeffRef(i) = 0;
|
||||
else
|
||||
aux.coeffRef(i) /= si;
|
||||
}
|
||||
|
||||
result->col(j) = m_matV * aux;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product unitary x positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computePositiveUnitary(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computeUnitaryPositive(UnitaryType *unitary,
|
||||
PositiveType *positive) const
|
||||
{
|
||||
ei_assert(m_matU.cols() == m_matV.cols() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matV * m_sigma.asDiagonal() * m_matV.adjoint();
|
||||
}
|
||||
|
||||
/** Computes the polar decomposition of the matrix, as a product positive x unitary.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* Only for square matrices.
|
||||
*
|
||||
* \sa computeUnitaryPositive(), computeRotationScaling()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename UnitaryType, typename PositiveType>
|
||||
void SVD<MatrixType>::computePositiveUnitary(UnitaryType *positive,
|
||||
PositiveType *unitary) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
if(unitary) *unitary = m_matU * m_matV.adjoint();
|
||||
if(positive) *positive = m_matU * m_sigma.asDiagonal() * m_matU.adjoint();
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeScalingRotation(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename RotationType, typename ScalingType>
|
||||
void SVD<MatrixType>::computeRotationScaling(RotationType *rotation, ScalingType *scaling) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matV * sv.asDiagonal() * m_matV.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the matrix as a product scaling x rotation, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* This method requires the Geometry module.
|
||||
*
|
||||
* \sa computeRotationScaling(), computeUnitaryPositive()
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
template<typename ScalingType, typename RotationType>
|
||||
void SVD<MatrixType>::computeScalingRotation(ScalingType *scaling, RotationType *rotation) const
|
||||
{
|
||||
ei_assert(m_matU.rows() == m_matV.rows() && "Polar decomposition is only for square matrices");
|
||||
Scalar x = (m_matU * m_matV.adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> sv(m_sigma);
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling) scaling->lazyAssign(m_matU * sv.asDiagonal() * m_matU.adjoint());
|
||||
if(rotation)
|
||||
{
|
||||
MatrixType m(m_matU);
|
||||
m.col(0) /= x;
|
||||
rotation->lazyAssign(m * m_matV.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \svd_module
|
||||
* \returns the SVD decomposition of \c *this
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline SVD<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::svd() const
|
||||
{
|
||||
return SVD<PlainObject>(derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_SVD_H
|
@ -1,42 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_TRIANGULAR_SOLVER2_H
|
||||
#define EIGEN_TRIANGULAR_SOLVER2_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
const unsigned int UnitDiagBit = UnitDiag;
|
||||
const unsigned int SelfAdjointBit = SelfAdjoint;
|
||||
const unsigned int UpperTriangularBit = Upper;
|
||||
const unsigned int LowerTriangularBit = Lower;
|
||||
|
||||
const unsigned int UpperTriangular = Upper;
|
||||
const unsigned int LowerTriangular = Lower;
|
||||
const unsigned int UnitUpperTriangular = UnitUpper;
|
||||
const unsigned int UnitLowerTriangular = UnitLower;
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
template<typename OtherDerived>
|
||||
typename ExpressionType::PlainObject
|
||||
Flagged<ExpressionType,Added,Removed>::solveTriangular(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
return m_matrix.template triangularView<Added>().solve(other.derived());
|
||||
}
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
template<typename OtherDerived>
|
||||
void Flagged<ExpressionType,Added,Removed>::solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
m_matrix.template triangularView<Added>().solveInPlace(other.derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_TRIANGULAR_SOLVER2_H
|
@ -1,94 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN2_VECTORBLOCK_H
|
||||
#define EIGEN2_VECTORBLOCK_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \deprecated use DenseMase::head(Index) */
|
||||
template<typename Derived>
|
||||
inline VectorBlock<Derived>
|
||||
MatrixBase<Derived>::start(Index size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<Derived>(derived(), 0, size);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::head(Index) */
|
||||
template<typename Derived>
|
||||
inline const VectorBlock<const Derived>
|
||||
MatrixBase<Derived>::start(Index size) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<const Derived>(derived(), 0, size);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::tail(Index) */
|
||||
template<typename Derived>
|
||||
inline VectorBlock<Derived>
|
||||
MatrixBase<Derived>::end(Index size)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<Derived>(derived(), this->size() - size, size);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::tail(Index) */
|
||||
template<typename Derived>
|
||||
inline const VectorBlock<const Derived>
|
||||
MatrixBase<Derived>::end(Index size) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<const Derived>(derived(), this->size() - size, size);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::head() */
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline VectorBlock<Derived,Size>
|
||||
MatrixBase<Derived>::start()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<Derived,Size>(derived(), 0);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::head() */
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline const VectorBlock<const Derived,Size>
|
||||
MatrixBase<Derived>::start() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<const Derived,Size>(derived(), 0);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::tail() */
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline VectorBlock<Derived,Size>
|
||||
MatrixBase<Derived>::end()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<Derived, Size>(derived(), size() - Size);
|
||||
}
|
||||
|
||||
/** \deprecated use DenseMase::tail() */
|
||||
template<typename Derived>
|
||||
template<int Size>
|
||||
inline const VectorBlock<const Derived,Size>
|
||||
MatrixBase<Derived>::end() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return VectorBlock<const Derived, Size>(derived(), size() - Size);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_VECTORBLOCK_H
|
@ -346,40 +346,6 @@ template<typename _MatrixType> class SelfAdjointEigenSolver
|
||||
*/
|
||||
static const int m_maxIterations = 30;
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
EIGEN_DEVICE_FUNC
|
||||
SelfAdjointEigenSolver(const MatrixType& matrix, bool computeEigenvectors)
|
||||
: m_eivec(matrix.rows(), matrix.cols()),
|
||||
m_eivalues(matrix.cols()),
|
||||
m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
compute(matrix, computeEigenvectors);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
SelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true)
|
||||
: m_eivec(matA.cols(), matA.cols()),
|
||||
m_eivalues(matA.cols()),
|
||||
m_subdiag(matA.cols() > 1 ? matA.cols() - 1 : 1),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
static_cast<GeneralizedSelfAdjointEigenSolver<MatrixType>*>(this)->compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
void compute(const MatrixType& matrix, bool computeEigenvectors)
|
||||
{
|
||||
compute(matrix, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
void compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true)
|
||||
{
|
||||
compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
|
||||
}
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
protected:
|
||||
MatrixType m_eivec;
|
||||
RealVectorType m_eivalues;
|
||||
|
@ -481,7 +481,6 @@ MatrixBase<Derived>::partialPivLu() const
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
@ -499,8 +498,6 @@ MatrixBase<Derived>::lu() const
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_PARTIALLU_H
|
||||
|
@ -369,17 +369,6 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
|
||||
template<typename OtherDerived>
|
||||
Derived& operator*=(const SparseMatrixBase<OtherDerived>& other);
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
// deprecated
|
||||
template<typename OtherDerived>
|
||||
typename internal::plain_matrix_type_column_major<OtherDerived>::type
|
||||
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
// deprecated
|
||||
template<typename OtherDerived>
|
||||
void solveTriangularInPlace(MatrixBase<OtherDerived>& other) const;
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
template<int Mode>
|
||||
inline const SparseTriangularView<Derived, Mode> triangularView() const;
|
||||
|
||||
|
@ -305,30 +305,6 @@ void SparseTriangularView<ExpressionType,Mode>::solveInPlace(SparseMatrixBase<Ot
|
||||
// other = otherCopy;
|
||||
}
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
|
||||
// deprecated stuff:
|
||||
|
||||
/** \deprecated */
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
void SparseMatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
this->template triangular<Flags&(Upper|Lower)>().solveInPlace(other);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
typename internal::plain_matrix_type_column_major<OtherDerived>::type
|
||||
SparseMatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
typename internal::plain_matrix_type_column_major<OtherDerived>::type res(other);
|
||||
derived().solveTriangularInPlace(res);
|
||||
return res;
|
||||
}
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SPARSETRIANGULARSOLVER_H
|
||||
|
@ -9,11 +9,8 @@ and gives tips to help porting your application from Eigen2 to Eigen3.
|
||||
|
||||
\section CompatibilitySupport Eigen2 compatibility support
|
||||
|
||||
In order to ease the switch from Eigen2 to Eigen3, Eigen3 features \subpage Eigen2SupportModes "Eigen2 support modes".
|
||||
|
||||
The quick way to enable this is to define the \c EIGEN2_SUPPORT preprocessor token \b before including any Eigen header (typically it should be set in your project options).
|
||||
|
||||
A more powerful, \em staged migration path is also provided, which may be useful to migrate larger projects from Eigen2 to Eigen3. This is explained in the \ref Eigen2SupportModes "Eigen 2 support modes" page.
|
||||
Up to version 3.2 %Eigen provides <a href="http://eigen.tuxfamily.org/dox/Eigen2SupportModes.html">Eigen2 support modes</a>. These are removed now, because they were barely used anymore and became hard to maintain after internal re-designs.
|
||||
You can still use them by first <a href="http://eigen.tuxfamily.org/dox/Eigen2ToEigen3.html">porting your code to Eigen 3.2</a>.
|
||||
|
||||
\section Using The USING_PART_OF_NAMESPACE_EIGEN macro
|
||||
|
||||
|
@ -1,93 +0,0 @@
|
||||
namespace Eigen {
|
||||
|
||||
/** \page Eigen2SupportModes Eigen 2 support modes
|
||||
|
||||
This page documents the Eigen2 support modes, a powerful tool to help migrating your project from Eigen 2 to Eigen 3.
|
||||
Don't miss our page on \ref Eigen2ToEigen3 "API changes" between Eigen 2 and Eigen 3.
|
||||
|
||||
\eigenAutoToc
|
||||
|
||||
\section EIGEN2_SUPPORT_Macro The quick way: define EIGEN2_SUPPORT
|
||||
|
||||
By defining EIGEN2_SUPPORT before including any Eigen 3 header, you get back a large part of the Eigen 2 API, while keeping the Eigen 3 API and ABI unchanged.
|
||||
|
||||
This defaults to the \ref Stage30 "stage 30" described below.
|
||||
|
||||
The rest of this page describes an optional, more powerful \em staged migration path.
|
||||
|
||||
\section StagedMigrationPathOverview Overview of the staged migration path
|
||||
|
||||
The primary reason why EIGEN2_SUPPORT alone may not be enough to migrate a large project from Eigen 2 to Eigen 3 is that some of the Eigen 2 API is inherently incompatible with the Eigen 3 API. This happens when the same identifier is used in Eigen 2 and in Eigen 3 with different meanings. To help migrate projects that rely on such API, we provide a staged migration path allowing to perform the migration \em incrementally.
|
||||
|
||||
It goes as follows:
|
||||
\li Step 0: start with a project using Eigen 2.
|
||||
\li Step 1: build your project against Eigen 3 with \ref Stage10 "Eigen 2 support stage 10". This mode enables maximum compatibility with the Eigen 2 API, with just a few exceptions.
|
||||
\li Step 2: build your project against Eigen 3 with \ref Stage20 "Eigen 2 support stage 20". This mode forces you to add eigen2_ prefixes to the Eigen2 identifiers that conflict with Eigen 3 API.
|
||||
\li Step 3: build your project against Eigen 3 with \ref Stage30 "Eigen 2 support stage 30". This mode enables the full Eigen 3 API.
|
||||
\li Step 4: build your project against Eigen 3 with \ref Stage40 "Eigen 2 support stage 40". This mode enables the full Eigen 3 strictness on matters, such as const-correctness, where Eigen 2 was looser.
|
||||
\li Step 5: build your project against Eigen 3 without any Eigen 2 support mode.
|
||||
|
||||
\section Stage10 Stage 10: define EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API
|
||||
|
||||
Enable this mode by defining the EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API preprocessor macro before including any Eigen 3 header.
|
||||
|
||||
This mode maximizes support for the Eigen 2 API. As a result, it does not offer the full Eigen 3 API. Also, it doesn't offer quite 100% of the Eigen 2 API.
|
||||
|
||||
The part of the Eigen 3 API that is not present in this mode, is Eigen 3's Geometry module. Indeed, this mode completely replaces it by a copy of Eigen 2's Geometry module.
|
||||
|
||||
The parts of the API that are still not 100% Eigen 2 compatible in this mode are:
|
||||
\li Dot products over complex numbers. Eigen 2's dot product was linear in the first variable. Eigen 3's dot product is linear in the second variable. In other words, the Eigen 2 code \code x.dot(y) \endcode is equivalent to the Eigen 3 code \code y.dot(x) \endcode In yet other words, dot products are complex-conjugated in Eigen 3 compared to Eigen 2. The switch to the new convention was commanded by common usage, especially with the notation \f$ x^Ty \f$ for dot products of column-vectors.
|
||||
\li The Sparse module.
|
||||
\li Certain fine details of linear algebraic decompositions. For example, LDLT decomposition is now pivoting in Eigen 3 whereas it wasn't in Eigen 2, so code that was relying on its underlying matrix structure will break.
|
||||
\li Usage of Eigen types in STL containers, \ref Eigen2ToEigen3 "as explained on this page".
|
||||
|
||||
\section Stage20 Stage 20: define EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS
|
||||
|
||||
Enable this mode by defining the EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API preprocessor macro before including any Eigen 3 header.
|
||||
|
||||
This mode removes the Eigen 2 API that is directly conflicting with Eigen 3 API. Instead, these bits of Eigen 2 API remain available with eigen2_ prefixes. The main examples of such API are:
|
||||
\li the whole Geometry module. For example, replace \c Quaternion by \c eigen2_Quaternion, replace \c Transform3f by \c eigen2_Transform3f, etc.
|
||||
\li the lu() method to obtain a LU decomposition. Replace by eigen2_lu().
|
||||
|
||||
There is also one more eigen2_-prefixed identifier that you should know about, even though its use is not checked at compile time by this mode: the dot() method. As was discussed above, over complex numbers, its meaning is different between Eigen 2 and Eigen 3. You can use eigen2_dot() to get the Eigen 2 behavior.
|
||||
|
||||
\section Stage30 Stage 30: define EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
|
||||
|
||||
Enable this mode by defining the EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API preprocessor macro before including any Eigen 3 header. Also, this mode is what you get by default when you just define EIGEN2_SUPPORT.
|
||||
|
||||
This mode gives you the full unaltered Eigen 3 API, while still keeping as much support as possible for the Eigen 2 API.
|
||||
|
||||
The eigen2_-prefixed identifiers are still available, but at this stage you should now replace them by Eigen 3 identifiers. Have a look at our page on \ref Eigen2ToEigen3 "API changes" between Eigen 2 and Eigen 3.
|
||||
|
||||
\section Stage40 Stage 40: define EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS
|
||||
|
||||
Enable this mode by defining the EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS preprocessor macro before including any Eigen 3 header.
|
||||
|
||||
This mode tightens the last bits of strictness, especially const-correctness, that had to be loosened to support what Eigen 2 allowed. For example, this code compiled in Eigen 2:
|
||||
\code
|
||||
const float array[4];
|
||||
x = Map<Vector4f>(array);
|
||||
\endcode
|
||||
That allowed to circumvent constness. This is no longer allowed in Eigen 3. If you have to map const data in Eigen 3, map it as a const-qualified type. However, rather than explictly constructing Map objects, we strongly encourage you to use the static Map methods instead, as they take care of all of this for you:
|
||||
\code
|
||||
const float array[4];
|
||||
x = Vector4f::Map(array);
|
||||
\endcode
|
||||
This lets Eigen do the right thing for you and works equally well in Eigen 2 and in Eigen 3.
|
||||
|
||||
\section FinallyDropAllEigen2Support Finally drop all Eigen 2 support
|
||||
|
||||
Stage 40 is the first where it's "comfortable" to stay for a little longer period, since it preserves 100% Eigen 3 compatibility. However, we still encourage you to complete your migration as quickly as possible. While we do run the Eigen 2 test suite against Eigen 3's stage 10 support mode, we can't guarantee the same level of support and quality assurance for Eigen 2 support as we do for Eigen 3 itself, especially not in the long term. \ref Eigen2ToEigen3 "This page" describes a large part of the changes that you may need to perform.
|
||||
|
||||
\section ABICompatibility What about ABI compatibility?
|
||||
|
||||
It goes as follows:
|
||||
\li Stage 10 already is ABI compatible with Eigen 3 for the basic (Matrix, Array, SparseMatrix...) types. However, since this stage uses a copy of Eigen 2's Geometry module instead of Eigen 3's own Geometry module, the ABI in the Geometry module is not Eigen 3 compatible.
|
||||
\li Stage 20 removes the Eigen 3-incompatible Eigen 2 Geometry module (it remains available with eigen2_ prefix). So at this stage, all the identifiers that exist in Eigen 3 have the Eigen 3 ABI (and API).
|
||||
\li Stage 30 introduces the remaining Eigen 3 identifiers. So at this stage, you have the full Eigen 3 ABI.
|
||||
\li Stage 40 is no different than Stage 30 in these matters.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
}
|
@ -1584,7 +1584,6 @@ PREDEFINED = EIGEN_EMPTY_STRUCT \
|
||||
EIGEN_QT_SUPPORT \
|
||||
EIGEN_STRONG_INLINE=inline \
|
||||
EIGEN_DEVICE_FUNC= \
|
||||
"EIGEN2_SUPPORT_STAGE=99" \
|
||||
"EIGEN_MAKE_CWISE_BINARY_OP(METHOD,FUNCTOR)=template<typename OtherDerived> const CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived> METHOD(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const;" \
|
||||
"EIGEN_CWISE_PRODUCT_RETURN_TYPE(LHS,RHS)=CwiseBinaryOp<internal::scalar_product_op<typename LHS::Scalar, typename RHS::Scalar >, const LHS, const RHS>"
|
||||
|
||||
@ -1601,8 +1600,7 @@ EXPAND_AS_DEFINED = EIGEN_MAKE_TYPEDEFS \
|
||||
EIGEN_CWISE_BINOP_RETURN_TYPE \
|
||||
EIGEN_CURRENT_STORAGE_BASE_CLASS \
|
||||
EIGEN_MATHFUNC_IMPL \
|
||||
_EIGEN_GENERIC_PUBLIC_INTERFACE \
|
||||
EIGEN2_SUPPORT
|
||||
_EIGEN_GENERIC_PUBLIC_INTERFACE
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will remove all references to function-like macros
|
||||
|
@ -5,7 +5,7 @@ namespace Eigen {
|
||||
You can control some aspects of %Eigen by defining the preprocessor tokens using \c \#define. These macros
|
||||
should be defined before any %Eigen headers are included. Often they are best set in the project options.
|
||||
|
||||
This page lists the preprocesor tokens recognised by %Eigen.
|
||||
This page lists the preprocessor tokens recognized by %Eigen.
|
||||
|
||||
\eigenAutoToc
|
||||
|
||||
@ -18,10 +18,9 @@ one option, and other parts (or libraries that you use) are compiled with anothe
|
||||
fail to link or exhibit subtle bugs. Nevertheless, these options can be useful for people who know what they
|
||||
are doing.
|
||||
|
||||
- \b EIGEN2_SUPPORT - if defined, enables the Eigen2 compatibility mode. This is meant to ease the transition
|
||||
of Eigen2 to Eigen3 (see \ref Eigen2ToEigen3). Not defined by default.
|
||||
- \b EIGEN2_SUPPORT_STAGEnn_xxx (for various values of nn and xxx) - staged migration path from Eigen2 to
|
||||
Eigen3; see \ref Eigen2SupportModes.
|
||||
- \b EIGEN2_SUPPORT and \b EIGEN2_SUPPORT_STAGEnn_xxx are disabled starting from the 3.3 release.
|
||||
Defining one of these will raise a compile-error. If you need to compile Eigen2 code,
|
||||
<a href="http://eigen.tuxfamily.org/index.php?title=Eigen2">check this site</a>.
|
||||
- \b EIGEN_DEFAULT_DENSE_INDEX_TYPE - the type for column and row indices in matrices, vectors and array
|
||||
(DenseBase::Index). Set to \c std::ptrdiff_t by default.
|
||||
- \b EIGEN_DEFAULT_IO_FORMAT - the IOFormat to use when printing a matrix if no %IOFormat is specified.
|
||||
@ -55,7 +54,7 @@ run time. However, these assertions do cost time and can thus be turned off.
|
||||
|
||||
\section TopicPreprocessorDirectivesPerformance Alignment, vectorization and performance tweaking
|
||||
|
||||
- \b EIGEN_MALLOC_ALREADY_ALIGNED - Can be set to 0 or 1 to tell whether default system malloc already
|
||||
- \b EIGEN_MALLOC_ALREADY_ALIGNED - Can be set to 0 or 1 to tell whether default system \c malloc already
|
||||
returns aligned buffers. In not defined, then this information is automatically deduced from the compiler
|
||||
and system preprocessor tokens.
|
||||
- \b EIGEN_DONT_ALIGN - disables alignment completely. %Eigen will not try to align its objects and does not
|
||||
|
@ -1,18 +0,0 @@
|
||||
#define EIGEN2_SUPPORT
|
||||
#include <Eigen/Core>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
Matrix3i m = Matrix3i::Random();
|
||||
cout << "Here is the matrix m:" << endl << m << endl;
|
||||
Matrix3i n = Matrix3i::Random();
|
||||
cout << "And here is the matrix n:" << endl << n << endl;
|
||||
cout << "The coefficient-wise product of m and n is:" << endl;
|
||||
cout << m.cwise() * n << endl;
|
||||
cout << "Taking the cube of the coefficients of m yields:" << endl;
|
||||
cout << m.cwise().pow(3) << endl;
|
||||
}
|
@ -157,7 +157,6 @@ ei_add_test(vectorization_logic)
|
||||
ei_add_test(basicstuff)
|
||||
ei_add_test(linearstructure)
|
||||
ei_add_test(integer_types)
|
||||
ei_add_test(cwiseop)
|
||||
ei_add_test(unalignedcount)
|
||||
ei_add_test(exceptions)
|
||||
ei_add_test(redux)
|
||||
@ -258,8 +257,6 @@ if(QT4_FOUND)
|
||||
ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
|
||||
endif(QT4_FOUND)
|
||||
|
||||
ei_add_test(eigen2support)
|
||||
|
||||
if(UMFPACK_FOUND)
|
||||
ei_add_test(umfpack_support "" "${UMFPACK_ALL_LIBS}")
|
||||
endif()
|
||||
@ -303,7 +300,7 @@ ei_add_property(EIGEN_TESTING_SUMMARY "Sparse lib flags: ${SPARSE_LIBS}\n")
|
||||
|
||||
option(EIGEN_TEST_EIGEN2 "Run whole Eigen2 test suite against EIGEN2_SUPPORT" OFF)
|
||||
if(EIGEN_TEST_EIGEN2)
|
||||
add_subdirectory(eigen2)
|
||||
message(WARNING "The Eigen2 test suite has been removed")
|
||||
endif()
|
||||
|
||||
|
||||
|
182
test/cwiseop.cpp
182
test/cwiseop.cpp
@ -1,182 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN2_SUPPORT
|
||||
#define EIGEN_NO_STATIC_ASSERT
|
||||
#include "main.h"
|
||||
#include <functional>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<typename Scalar> struct AddIfNull {
|
||||
const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
|
||||
enum { Cost = NumTraits<Scalar>::AddCost };
|
||||
};
|
||||
|
||||
template<typename MatrixType>
|
||||
typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
|
||||
cwiseops_real_only(MatrixType& m1, MatrixType& m2, MatrixType& m3, MatrixType& mones)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
|
||||
m3 = m1.cwise().abs().cwise().sqrt();
|
||||
VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
|
||||
VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
|
||||
VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
|
||||
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
|
||||
m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
|
||||
VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
|
||||
m3 = m1.cwise().abs();
|
||||
VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
|
||||
|
||||
// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
|
||||
VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
|
||||
m3 = m1;
|
||||
m3.cwise() /= m2;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() / m2);
|
||||
|
||||
return Scalar(0);
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
|
||||
cwiseops_real_only(MatrixType& , MatrixType& , MatrixType& , MatrixType& )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename MatrixType> void cwiseops(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Index Index;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m1bis = m1,
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
m4(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
mones = MatrixType::Ones(rows, cols),
|
||||
identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Identity(rows, rows);
|
||||
VectorType vzero = VectorType::Zero(rows),
|
||||
vones = VectorType::Ones(rows),
|
||||
v3(rows);
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
// test Zero, Ones, Constant, and the set* variants
|
||||
m3 = MatrixType::Constant(rows, cols, s1);
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<rows; ++i)
|
||||
{
|
||||
VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
|
||||
VERIFY_IS_APPROX(mones(i,j), Scalar(1));
|
||||
VERIFY_IS_APPROX(m3(i,j), s1);
|
||||
}
|
||||
VERIFY(mzero.isZero());
|
||||
VERIFY(mones.isOnes());
|
||||
VERIFY(m3.isConstant(s1));
|
||||
VERIFY(identity.isIdentity());
|
||||
VERIFY_IS_APPROX(m4.setConstant(s1), m3);
|
||||
VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
|
||||
VERIFY_IS_APPROX(m4.setZero(), mzero);
|
||||
VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
|
||||
VERIFY_IS_APPROX(m4.setOnes(), mones);
|
||||
VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
|
||||
m4.fill(s1);
|
||||
VERIFY_IS_APPROX(m4, m3);
|
||||
|
||||
VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
|
||||
VERIFY_IS_APPROX(v3.setZero(rows), vzero);
|
||||
VERIFY_IS_APPROX(v3.setOnes(rows), vones);
|
||||
|
||||
m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
|
||||
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
|
||||
|
||||
VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
|
||||
VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
|
||||
m3 = m1; m3.cwise() += 1;
|
||||
VERIFY_IS_APPROX(m1 + mones, m3);
|
||||
m3 = m1; m3.cwise() -= 1;
|
||||
VERIFY_IS_APPROX(m1 - mones, m3);
|
||||
|
||||
VERIFY_IS_APPROX(m2, m2.cwise() * mones);
|
||||
VERIFY_IS_APPROX(m1.cwise() * m2, m2.cwise() * m1);
|
||||
m3 = m1;
|
||||
m3.cwise() *= m2;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() * m2);
|
||||
|
||||
VERIFY_IS_APPROX(mones, m2.cwise()/m2);
|
||||
|
||||
// check min
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
|
||||
|
||||
// check max
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
|
||||
|
||||
VERIFY( (m1.cwise() == m1).all() );
|
||||
VERIFY( (m1.cwise() != m2).any() );
|
||||
VERIFY(!(m1.cwise() == (m1+mones)).any() );
|
||||
if (rows*cols>1)
|
||||
{
|
||||
m3 = m1;
|
||||
m3(r,c) += 1;
|
||||
VERIFY( (m1.cwise() == m3).any() );
|
||||
VERIFY( !(m1.cwise() == m3).all() );
|
||||
}
|
||||
VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
|
||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||
|
||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||
|
||||
cwiseops_real_only(m1, m2, m3, mones);
|
||||
}
|
||||
|
||||
void test_cwiseop()
|
||||
{
|
||||
for(int i = 0; i < g_repeat ; i++) {
|
||||
CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( cwiseops(Matrix4d()) );
|
||||
CALL_SUBTEST_3( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_4( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_5( cwiseops(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( cwiseops(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
add_custom_target(eigen2_buildtests)
|
||||
add_custom_target(eigen2_check COMMAND "ctest -R eigen2")
|
||||
add_dependencies(eigen2_check eigen2_buildtests)
|
||||
add_dependencies(buildtests eigen2_buildtests)
|
||||
|
||||
add_definitions("-DEIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API")
|
||||
|
||||
# Disable unused warnings for this module
|
||||
# As EIGEN2 support is deprecated, it is not really worth fixing them
|
||||
ei_add_cxx_compiler_flag("-Wno-unused-local-typedefs")
|
||||
ei_add_cxx_compiler_flag("-Wno-unused-but-set-variable")
|
||||
|
||||
ei_add_test(eigen2_meta)
|
||||
ei_add_test(eigen2_sizeof)
|
||||
ei_add_test(eigen2_dynalloc)
|
||||
ei_add_test(eigen2_nomalloc)
|
||||
#ei_add_test(eigen2_first_aligned)
|
||||
ei_add_test(eigen2_mixingtypes)
|
||||
#ei_add_test(eigen2_packetmath)
|
||||
ei_add_test(eigen2_unalignedassert)
|
||||
#ei_add_test(eigen2_vectorization_logic)
|
||||
ei_add_test(eigen2_basicstuff)
|
||||
ei_add_test(eigen2_linearstructure)
|
||||
ei_add_test(eigen2_cwiseop)
|
||||
ei_add_test(eigen2_sum)
|
||||
ei_add_test(eigen2_product_small)
|
||||
ei_add_test(eigen2_product_large ${EI_OFLAG})
|
||||
ei_add_test(eigen2_adjoint)
|
||||
ei_add_test(eigen2_submatrices)
|
||||
ei_add_test(eigen2_miscmatrices)
|
||||
ei_add_test(eigen2_commainitializer)
|
||||
ei_add_test(eigen2_smallvectors)
|
||||
ei_add_test(eigen2_map)
|
||||
ei_add_test(eigen2_array)
|
||||
ei_add_test(eigen2_triangular)
|
||||
ei_add_test(eigen2_cholesky " " "${GSL_LIBRARIES}")
|
||||
ei_add_test(eigen2_lu ${EI_OFLAG})
|
||||
ei_add_test(eigen2_determinant ${EI_OFLAG})
|
||||
ei_add_test(eigen2_inverse)
|
||||
ei_add_test(eigen2_qr)
|
||||
ei_add_test(eigen2_eigensolver " " "${GSL_LIBRARIES}")
|
||||
ei_add_test(eigen2_svd)
|
||||
ei_add_test(eigen2_geometry)
|
||||
ei_add_test(eigen2_geometry_with_eigen2_prefix)
|
||||
ei_add_test(eigen2_hyperplane)
|
||||
ei_add_test(eigen2_parametrizedline)
|
||||
ei_add_test(eigen2_alignedbox)
|
||||
ei_add_test(eigen2_regression)
|
||||
ei_add_test(eigen2_stdvector)
|
||||
ei_add_test(eigen2_newstdvector)
|
||||
if(QT4_FOUND)
|
||||
ei_add_test(eigen2_qtvector " " "${QT_QTCORE_LIBRARY}")
|
||||
endif(QT4_FOUND)
|
||||
# no support for eigen2 sparse module
|
||||
# if(NOT EIGEN_DEFAULT_TO_ROW_MAJOR)
|
||||
# ei_add_test(eigen2_sparse_vector)
|
||||
# ei_add_test(eigen2_sparse_basic)
|
||||
# ei_add_test(eigen2_sparse_solvers " " "${SPARSE_LIBS}")
|
||||
# ei_add_test(eigen2_sparse_product)
|
||||
# endif()
|
||||
ei_add_test(eigen2_swap)
|
||||
ei_add_test(eigen2_visitor)
|
||||
ei_add_test(eigen2_bug_132)
|
||||
|
||||
ei_add_test(eigen2_prec_inverse_4x4 ${EI_OFLAG})
|
@ -1,101 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void adjoint(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Transpose.h Conjugate.h Dot.h
|
||||
*/
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
RealScalar largerEps = test_precision<RealScalar>();
|
||||
if (ei_is_same_type<RealScalar,float>::ret)
|
||||
largerEps = RealScalar(1e-3f);
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = SquareMatrixType::Identity(rows, rows),
|
||||
square = SquareMatrixType::Random(rows, rows);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
v3 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
Scalar s1 = ei_random<Scalar>(),
|
||||
s2 = ei_random<Scalar>();
|
||||
|
||||
// check basic compatibility of adjoint, transpose, conjugate
|
||||
VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(), m1);
|
||||
VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(), m1);
|
||||
|
||||
// check multiplicative behavior
|
||||
VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(), m2.adjoint() * m1);
|
||||
VERIFY_IS_APPROX((s1 * m1).adjoint(), ei_conj(s1) * m1.adjoint());
|
||||
|
||||
// check basic properties of dot, norm, norm2
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
VERIFY(ei_isApprox((s1 * v1 + s2 * v2).eigen2_dot(v3), s1 * v1.eigen2_dot(v3) + s2 * v2.eigen2_dot(v3), largerEps));
|
||||
VERIFY(ei_isApprox(v3.eigen2_dot(s1 * v1 + s2 * v2), ei_conj(s1)*v3.eigen2_dot(v1)+ei_conj(s2)*v3.eigen2_dot(v2), largerEps));
|
||||
VERIFY_IS_APPROX(ei_conj(v1.eigen2_dot(v2)), v2.eigen2_dot(v1));
|
||||
VERIFY_IS_APPROX(ei_real(v1.eigen2_dot(v1)), v1.squaredNorm());
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm());
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(ei_abs(vzero.eigen2_dot(v1)), static_cast<RealScalar>(1));
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1));
|
||||
|
||||
// check compatibility of dot and adjoint
|
||||
VERIFY(ei_isApprox(v1.eigen2_dot(square * v2), (square.adjoint() * v1).eigen2_dot(v2), largerEps));
|
||||
|
||||
// like in testBasicStuff, test operator() to check const-qualification
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
VERIFY_IS_APPROX(m1.conjugate()(r,c), ei_conj(m1(r,c)));
|
||||
VERIFY_IS_APPROX(m1.adjoint()(c,r), ei_conj(m1(r,c)));
|
||||
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
{
|
||||
// check that Random().normalized() works: tricky as the random xpr must be evaluated by
|
||||
// normalized() in order to produce a consistent result.
|
||||
VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
|
||||
}
|
||||
|
||||
// check inplace transpose
|
||||
m3 = m1;
|
||||
m3.transposeInPlace();
|
||||
VERIFY_IS_APPROX(m3,m1.transpose());
|
||||
m3.transposeInPlace();
|
||||
VERIFY_IS_APPROX(m3,m1);
|
||||
|
||||
}
|
||||
|
||||
void test_eigen2_adjoint()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( adjoint(Matrix3d()) );
|
||||
CALL_SUBTEST_3( adjoint(Matrix4f()) );
|
||||
CALL_SUBTEST_4( adjoint(MatrixXcf(4, 4)) );
|
||||
CALL_SUBTEST_5( adjoint(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST_6( adjoint(MatrixXf(21, 21)) );
|
||||
}
|
||||
// test a large matrix only once
|
||||
CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename BoxType> void alignedbox(const BoxType& _box)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
AlignedBox.h
|
||||
*/
|
||||
|
||||
const int dim = _box.dim();
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
RealScalar s1 = ei_random<RealScalar>(0,1);
|
||||
|
||||
BoxType b0(dim);
|
||||
BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
|
||||
BoxType b2;
|
||||
|
||||
b0.extend(p0);
|
||||
b0.extend(p1);
|
||||
VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
|
||||
VERIFY(!b0.contains(p0 + (1+s1)*(p1-p0)));
|
||||
|
||||
(b2 = b0).extend(b1);
|
||||
VERIFY(b2.contains(b0));
|
||||
VERIFY(b2.contains(b1));
|
||||
VERIFY_IS_APPROX(b2.clamp(b0), b0);
|
||||
|
||||
// casting
|
||||
const int Dim = BoxType::AmbientDimAtCompileTime;
|
||||
typedef typename GetDifferentType<Scalar>::type OtherScalar;
|
||||
AlignedBox<OtherScalar,Dim> hp1f = b0.template cast<OtherScalar>();
|
||||
VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),b0);
|
||||
AlignedBox<Scalar,Dim> hp1d = b0.template cast<Scalar>();
|
||||
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),b0);
|
||||
}
|
||||
|
||||
void test_eigen2_alignedbox()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( alignedbox(AlignedBox<float,2>()) );
|
||||
CALL_SUBTEST_2( alignedbox(AlignedBox<float,3>()) );
|
||||
CALL_SUBTEST_3( alignedbox(AlignedBox<double,4>()) );
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Array>
|
||||
|
||||
template<typename MatrixType> void array(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Array.cpp
|
||||
*/
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
Scalar s1 = ei_random<Scalar>(),
|
||||
s2 = ei_random<Scalar>();
|
||||
|
||||
// scalar addition
|
||||
VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
|
||||
VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
|
||||
VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
|
||||
m3 = m1;
|
||||
m3.cwise() += s2;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() + s2);
|
||||
m3 = m1;
|
||||
m3.cwise() -= s1;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() - s1);
|
||||
|
||||
// reductions
|
||||
VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
|
||||
VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
|
||||
if (!ei_isApprox(m1.sum(), (m1+m2).sum()))
|
||||
VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
|
||||
VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
|
||||
}
|
||||
|
||||
template<typename MatrixType> void comparisons(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
VERIFY(((m1.cwise() + Scalar(1)).cwise() > m1).all());
|
||||
VERIFY(((m1.cwise() - Scalar(1)).cwise() < m1).all());
|
||||
if (rows*cols>1)
|
||||
{
|
||||
m3 = m1;
|
||||
m3(r,c) += 1;
|
||||
VERIFY(! (m1.cwise() < m3).all() );
|
||||
VERIFY(! (m1.cwise() > m3).all() );
|
||||
}
|
||||
|
||||
// comparisons to scalar
|
||||
VERIFY( (m1.cwise() != (m1(r,c)+1) ).any() );
|
||||
VERIFY( (m1.cwise() > (m1(r,c)-1) ).any() );
|
||||
VERIFY( (m1.cwise() < (m1(r,c)+1) ).any() );
|
||||
VERIFY( (m1.cwise() == m1(r,c) ).any() );
|
||||
|
||||
// test Select
|
||||
VERIFY_IS_APPROX( (m1.cwise()<m2).select(m1,m2), m1.cwise().min(m2) );
|
||||
VERIFY_IS_APPROX( (m1.cwise()>m2).select(m1,m2), m1.cwise().max(m2) );
|
||||
Scalar mid = (m1.cwise().abs().minCoeff() + m1.cwise().abs().maxCoeff())/Scalar(2);
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<rows; ++i)
|
||||
m3(i,j) = ei_abs(m1(i,j))<mid ? 0 : m1(i,j);
|
||||
VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
|
||||
.select(MatrixType::Zero(rows,cols),m1), m3);
|
||||
// shorter versions:
|
||||
VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
|
||||
.select(0,m1), m3);
|
||||
VERIFY_IS_APPROX( (m1.cwise().abs().cwise()>=MatrixType::Constant(rows,cols,mid))
|
||||
.select(m1,0), m3);
|
||||
// even shorter version:
|
||||
VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<mid).select(0,m1), m3);
|
||||
|
||||
// count
|
||||
VERIFY(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).count() == rows*cols);
|
||||
VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).colwise().count().template cast<int>(), RowVectorXi::Constant(cols,rows));
|
||||
VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).rowwise().count().template cast<int>(), VectorXi::Constant(rows, cols));
|
||||
}
|
||||
|
||||
template<typename VectorType> void lpNorm(const VectorType& v)
|
||||
{
|
||||
VectorType u = VectorType::Random(v.size());
|
||||
|
||||
VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwise().abs().maxCoeff());
|
||||
VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwise().abs().sum());
|
||||
VERIFY_IS_APPROX(u.template lpNorm<2>(), ei_sqrt(u.cwise().abs().cwise().square().sum()));
|
||||
VERIFY_IS_APPROX(ei_pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.cwise().abs().cwise().pow(5).sum());
|
||||
}
|
||||
|
||||
void test_eigen2_array()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( array(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( array(Matrix2f()) );
|
||||
CALL_SUBTEST_3( array(Matrix4d()) );
|
||||
CALL_SUBTEST_4( array(MatrixXcf(3, 3)) );
|
||||
CALL_SUBTEST_5( array(MatrixXf(8, 12)) );
|
||||
CALL_SUBTEST_6( array(MatrixXi(8, 12)) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( comparisons(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( comparisons(Matrix2f()) );
|
||||
CALL_SUBTEST_3( comparisons(Matrix4d()) );
|
||||
CALL_SUBTEST_5( comparisons(MatrixXf(8, 12)) );
|
||||
CALL_SUBTEST_6( comparisons(MatrixXi(8, 12)) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( lpNorm(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( lpNorm(Vector2f()) );
|
||||
CALL_SUBTEST_3( lpNorm(Vector3d()) );
|
||||
CALL_SUBTEST_4( lpNorm(Vector4f()) );
|
||||
CALL_SUBTEST_5( lpNorm(VectorXf(16)) );
|
||||
CALL_SUBTEST_7( lpNorm(VectorXcd(10)) );
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void basicStuff(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
// this test relies a lot on Random.h, and there's not much more that we can do
|
||||
// to test it, hence I consider that we will have tested Random.h
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Identity(rows, rows),
|
||||
square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
Scalar x = ei_random<Scalar>();
|
||||
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
|
||||
m1.coeffRef(r,c) = x;
|
||||
VERIFY_IS_APPROX(x, m1.coeff(r,c));
|
||||
m1(r,c) = x;
|
||||
VERIFY_IS_APPROX(x, m1(r,c));
|
||||
v1.coeffRef(r) = x;
|
||||
VERIFY_IS_APPROX(x, v1.coeff(r));
|
||||
v1(r) = x;
|
||||
VERIFY_IS_APPROX(x, v1(r));
|
||||
v1[r] = x;
|
||||
VERIFY_IS_APPROX(x, v1[r]);
|
||||
|
||||
VERIFY_IS_APPROX( v1, v1);
|
||||
VERIFY_IS_NOT_APPROX( v1, 2*v1);
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1);
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.norm());
|
||||
VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1, v1);
|
||||
VERIFY_IS_APPROX( vzero, v1-v1);
|
||||
VERIFY_IS_APPROX( m1, m1);
|
||||
VERIFY_IS_NOT_APPROX( m1, 2*m1);
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( mzero, m1);
|
||||
VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1, m1);
|
||||
VERIFY_IS_APPROX( mzero, m1-m1);
|
||||
|
||||
// always test operator() on each read-only expression class,
|
||||
// in order to check const-qualifiers.
|
||||
// indeed, if an expression class (here Zero) is meant to be read-only,
|
||||
// hence has no _write() method, the corresponding MatrixBase method (here zero())
|
||||
// should return a const-qualified object so that it is the const-qualified
|
||||
// operator() that gets called, which in turn calls _read().
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1));
|
||||
|
||||
// now test copying a row-vector into a (column-)vector and conversely.
|
||||
square.col(r) = square.row(r).eval();
|
||||
Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
|
||||
rv = square.row(r);
|
||||
cv = square.col(r);
|
||||
VERIFY_IS_APPROX(rv, cv.transpose());
|
||||
|
||||
if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic)
|
||||
{
|
||||
VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1)));
|
||||
}
|
||||
|
||||
VERIFY_IS_APPROX(m3 = m1,m1);
|
||||
MatrixType m4;
|
||||
VERIFY_IS_APPROX(m4 = m1,m1);
|
||||
|
||||
// test swap
|
||||
m3 = m1;
|
||||
m1.swap(m2);
|
||||
VERIFY_IS_APPROX(m3, m2);
|
||||
if(rows*cols>=3)
|
||||
{
|
||||
VERIFY_IS_NOT_APPROX(m3, m1);
|
||||
}
|
||||
}
|
||||
|
||||
void test_eigen2_basicstuff()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( basicStuff(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( basicStuff(Matrix4d()) );
|
||||
CALL_SUBTEST_3( basicStuff(MatrixXcf(3, 3)) );
|
||||
CALL_SUBTEST_4( basicStuff(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST_5( basicStuff(MatrixXcd(20, 20)) );
|
||||
CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
|
||||
CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(10,10)) );
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
void test_eigen2_bug_132() {
|
||||
int size = 100;
|
||||
MatrixXd A(size, size);
|
||||
VectorXd b(size), c(size);
|
||||
{
|
||||
VectorXd y = A.transpose() * (b-c); // bug 132: infinite recursion in coeffRef
|
||||
VectorXd z = (b-c).transpose() * A; // bug 132: infinite recursion in coeffRef
|
||||
}
|
||||
|
||||
// the following ones weren't failing, but let's include them for completeness:
|
||||
{
|
||||
VectorXd y = A * (b-c);
|
||||
VectorXd z = (b-c).transpose() * A.transpose();
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN_NO_ASSERTION_CHECKING
|
||||
#include "main.h"
|
||||
#include <Eigen/Cholesky>
|
||||
#include <Eigen/LU>
|
||||
|
||||
#ifdef HAS_GSL
|
||||
#include "gsl_helper.h"
|
||||
#endif
|
||||
|
||||
template<typename MatrixType> void cholesky(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
LLT.h LDLT.h
|
||||
*/
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType a0 = MatrixType::Random(rows,cols);
|
||||
VectorType vecB = VectorType::Random(rows), vecX(rows);
|
||||
MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
|
||||
SquareMatrixType symm = a0 * a0.adjoint();
|
||||
// let's make sure the matrix is not singular or near singular
|
||||
MatrixType a1 = MatrixType::Random(rows,cols);
|
||||
symm += a1 * a1.adjoint();
|
||||
|
||||
#ifdef HAS_GSL
|
||||
if (ei_is_same_type<RealScalar,double>::ret)
|
||||
{
|
||||
typedef GslTraits<Scalar> Gsl;
|
||||
typename Gsl::Matrix gMatA=0, gSymm=0;
|
||||
typename Gsl::Vector gVecB=0, gVecX=0;
|
||||
convert<MatrixType>(symm, gSymm);
|
||||
convert<MatrixType>(symm, gMatA);
|
||||
convert<VectorType>(vecB, gVecB);
|
||||
convert<VectorType>(vecB, gVecX);
|
||||
Gsl::cholesky(gMatA);
|
||||
Gsl::cholesky_solve(gMatA, gVecB, gVecX);
|
||||
VectorType vecX(rows), _vecX, _vecB;
|
||||
convert(gVecX, _vecX);
|
||||
symm.llt().solve(vecB, &vecX);
|
||||
Gsl::prod(gSymm, gVecX, gVecB);
|
||||
convert(gVecB, _vecB);
|
||||
// test gsl itself !
|
||||
VERIFY_IS_APPROX(vecB, _vecB);
|
||||
VERIFY_IS_APPROX(vecX, _vecX);
|
||||
|
||||
Gsl::free(gMatA);
|
||||
Gsl::free(gSymm);
|
||||
Gsl::free(gVecB);
|
||||
Gsl::free(gVecX);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
LDLT<SquareMatrixType> ldlt(symm);
|
||||
VERIFY(ldlt.isPositiveDefinite());
|
||||
// in eigen3, LDLT is pivoting
|
||||
//VERIFY_IS_APPROX(symm, ldlt.matrixL() * ldlt.vectorD().asDiagonal() * ldlt.matrixL().adjoint());
|
||||
ldlt.solve(vecB, &vecX);
|
||||
VERIFY_IS_APPROX(symm * vecX, vecB);
|
||||
ldlt.solve(matB, &matX);
|
||||
VERIFY_IS_APPROX(symm * matX, matB);
|
||||
}
|
||||
|
||||
{
|
||||
LLT<SquareMatrixType> chol(symm);
|
||||
VERIFY(chol.isPositiveDefinite());
|
||||
VERIFY_IS_APPROX(symm, chol.matrixL() * chol.matrixL().adjoint());
|
||||
chol.solve(vecB, &vecX);
|
||||
VERIFY_IS_APPROX(symm * vecX, vecB);
|
||||
chol.solve(matB, &matX);
|
||||
VERIFY_IS_APPROX(symm * matX, matB);
|
||||
}
|
||||
|
||||
#if 0 // cholesky is not rank-revealing anyway
|
||||
// test isPositiveDefinite on non definite matrix
|
||||
if (rows>4)
|
||||
{
|
||||
SquareMatrixType symm = a0.block(0,0,rows,cols-4) * a0.block(0,0,rows,cols-4).adjoint();
|
||||
LLT<SquareMatrixType> chol(symm);
|
||||
VERIFY(!chol.isPositiveDefinite());
|
||||
LDLT<SquareMatrixType> cholnosqrt(symm);
|
||||
VERIFY(!cholnosqrt.isPositiveDefinite());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_eigen2_cholesky()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_2( cholesky(Matrix2d()) );
|
||||
CALL_SUBTEST_3( cholesky(Matrix3f()) );
|
||||
CALL_SUBTEST_4( cholesky(Matrix4d()) );
|
||||
CALL_SUBTEST_5( cholesky(MatrixXcd(7,7)) );
|
||||
CALL_SUBTEST_6( cholesky(MatrixXf(17,17)) );
|
||||
CALL_SUBTEST_7( cholesky(MatrixXd(33,33)) );
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
void test_eigen2_commainitializer()
|
||||
{
|
||||
Matrix3d m3;
|
||||
Matrix4d m4;
|
||||
|
||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
|
||||
|
||||
#ifndef _MSC_VER
|
||||
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
|
||||
#endif
|
||||
|
||||
double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
Matrix3d ref = Map<Matrix<double,3,3,RowMajor> >(data);
|
||||
|
||||
m3 = Matrix3d::Random();
|
||||
m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
|
||||
VERIFY_IS_APPROX(m3, ref );
|
||||
|
||||
Vector3d vec[3];
|
||||
vec[0] << 1, 4, 7;
|
||||
vec[1] << 2, 5, 8;
|
||||
vec[2] << 3, 6, 9;
|
||||
m3 = Matrix3d::Random();
|
||||
m3 << vec[0], vec[1], vec[2];
|
||||
VERIFY_IS_APPROX(m3, ref);
|
||||
|
||||
vec[0] << 1, 2, 3;
|
||||
vec[1] << 4, 5, 6;
|
||||
vec[2] << 7, 8, 9;
|
||||
m3 = Matrix3d::Random();
|
||||
m3 << vec[0].transpose(),
|
||||
4, 5, 6,
|
||||
vec[2].transpose();
|
||||
VERIFY_IS_APPROX(m3, ref);
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <functional>
|
||||
#include <Eigen/Array>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<typename Scalar> struct AddIfNull {
|
||||
const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
|
||||
enum { Cost = NumTraits<Scalar>::AddCost };
|
||||
};
|
||||
|
||||
template<typename MatrixType> void cwiseops(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
m4(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
mones = MatrixType::Ones(rows, cols),
|
||||
identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Identity(rows, rows),
|
||||
square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows),
|
||||
vones = VectorType::Ones(rows),
|
||||
v3(rows);
|
||||
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
|
||||
Scalar s1 = ei_random<Scalar>();
|
||||
|
||||
// test Zero, Ones, Constant, and the set* variants
|
||||
m3 = MatrixType::Constant(rows, cols, s1);
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<rows; ++i)
|
||||
{
|
||||
VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
|
||||
VERIFY_IS_APPROX(mones(i,j), Scalar(1));
|
||||
VERIFY_IS_APPROX(m3(i,j), s1);
|
||||
}
|
||||
VERIFY(mzero.isZero());
|
||||
VERIFY(mones.isOnes());
|
||||
VERIFY(m3.isConstant(s1));
|
||||
VERIFY(identity.isIdentity());
|
||||
VERIFY_IS_APPROX(m4.setConstant(s1), m3);
|
||||
VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
|
||||
VERIFY_IS_APPROX(m4.setZero(), mzero);
|
||||
VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
|
||||
VERIFY_IS_APPROX(m4.setOnes(), mones);
|
||||
VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
|
||||
m4.fill(s1);
|
||||
VERIFY_IS_APPROX(m4, m3);
|
||||
|
||||
VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
|
||||
VERIFY_IS_APPROX(v3.setZero(rows), vzero);
|
||||
VERIFY_IS_APPROX(v3.setOnes(rows), vones);
|
||||
|
||||
m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
|
||||
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
|
||||
|
||||
VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
|
||||
VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
|
||||
m3 = m1; m3.cwise() += 1;
|
||||
VERIFY_IS_APPROX(m1 + mones, m3);
|
||||
m3 = m1; m3.cwise() -= 1;
|
||||
VERIFY_IS_APPROX(m1 - mones, m3);
|
||||
|
||||
VERIFY_IS_APPROX(m2, m2.cwise() * mones);
|
||||
VERIFY_IS_APPROX(m1.cwise() * m2, m2.cwise() * m1);
|
||||
m3 = m1;
|
||||
m3.cwise() *= m2;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() * m2);
|
||||
|
||||
VERIFY_IS_APPROX(mones, m2.cwise()/m2);
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
{
|
||||
VERIFY_IS_APPROX(m1.cwise() / m2, m1.cwise() * (m2.cwise().inverse()));
|
||||
m3 = m1.cwise().abs().cwise().sqrt();
|
||||
VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
|
||||
VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
|
||||
VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
|
||||
|
||||
VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
|
||||
m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
|
||||
VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
|
||||
m3 = m1.cwise().abs();
|
||||
VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
|
||||
|
||||
// VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
|
||||
VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
|
||||
m3 = m1;
|
||||
m3.cwise() /= m2;
|
||||
VERIFY_IS_APPROX(m3, m1.cwise() / m2);
|
||||
}
|
||||
|
||||
// check min
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
|
||||
VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
|
||||
|
||||
// check max
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
|
||||
VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
|
||||
|
||||
VERIFY( (m1.cwise() == m1).all() );
|
||||
VERIFY( (m1.cwise() != m2).any() );
|
||||
VERIFY(!(m1.cwise() == (m1+mones)).any() );
|
||||
if (rows*cols>1)
|
||||
{
|
||||
m3 = m1;
|
||||
m3(r,c) += 1;
|
||||
VERIFY( (m1.cwise() == m3).any() );
|
||||
VERIFY( !(m1.cwise() == m3).all() );
|
||||
}
|
||||
VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
|
||||
VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
|
||||
VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
|
||||
|
||||
VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
|
||||
VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
|
||||
}
|
||||
|
||||
void test_eigen2_cwiseop()
|
||||
{
|
||||
for(int i = 0; i < g_repeat ; i++) {
|
||||
CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( cwiseops(Matrix4d()) );
|
||||
CALL_SUBTEST_3( cwiseops(MatrixXf(3, 3)) );
|
||||
CALL_SUBTEST_3( cwiseops(MatrixXf(22, 22)) );
|
||||
CALL_SUBTEST_4( cwiseops(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST_5( cwiseops(MatrixXd(20, 20)) );
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
|
||||
template<typename MatrixType> void determinant(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Determinant.h
|
||||
*/
|
||||
int size = m.rows();
|
||||
|
||||
MatrixType m1(size, size), m2(size, size);
|
||||
m1.setRandom();
|
||||
m2.setRandom();
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
Scalar x = ei_random<Scalar>();
|
||||
VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
|
||||
VERIFY_IS_APPROX((m1*m2).determinant(), m1.determinant() * m2.determinant());
|
||||
if(size==1) return;
|
||||
int i = ei_random<int>(0, size-1);
|
||||
int j;
|
||||
do {
|
||||
j = ei_random<int>(0, size-1);
|
||||
} while(j==i);
|
||||
m2 = m1;
|
||||
m2.row(i).swap(m2.row(j));
|
||||
VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
|
||||
m2 = m1;
|
||||
m2.col(i).swap(m2.col(j));
|
||||
VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
|
||||
VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
|
||||
VERIFY_IS_APPROX(ei_conj(m2.determinant()), m2.adjoint().determinant());
|
||||
m2 = m1;
|
||||
m2.row(i) += x*m2.row(j);
|
||||
VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
|
||||
m2 = m1;
|
||||
m2.row(i) *= x;
|
||||
VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x);
|
||||
}
|
||||
|
||||
void test_eigen2_determinant()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( determinant(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( determinant(Matrix<double, 2, 2>()) );
|
||||
CALL_SUBTEST_3( determinant(Matrix<double, 3, 3>()) );
|
||||
CALL_SUBTEST_4( determinant(Matrix<double, 4, 4>()) );
|
||||
CALL_SUBTEST_5( determinant(Matrix<std::complex<double>, 10, 10>()) );
|
||||
CALL_SUBTEST_6( determinant(MatrixXd(20, 20)) );
|
||||
}
|
||||
CALL_SUBTEST_6( determinant(MatrixXd(200, 200)) );
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#if EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#define ALIGNMENT 16
|
||||
#else
|
||||
#define ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
void check_handmade_aligned_malloc()
|
||||
{
|
||||
for(int i = 1; i < 1000; i++)
|
||||
{
|
||||
char *p = (char*)ei_handmade_aligned_malloc(i);
|
||||
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||
for(int j = 0; j < i; j++) p[j]=0;
|
||||
ei_handmade_aligned_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_malloc()
|
||||
{
|
||||
for(int i = 1; i < 1000; i++)
|
||||
{
|
||||
char *p = (char*)ei_aligned_malloc(i);
|
||||
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||
for(int j = 0; j < i; j++) p[j]=0;
|
||||
ei_aligned_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_new()
|
||||
{
|
||||
for(int i = 1; i < 1000; i++)
|
||||
{
|
||||
float *p = ei_aligned_new<float>(i);
|
||||
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||
for(int j = 0; j < i; j++) p[j]=0;
|
||||
ei_aligned_delete(p,i);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_stack_alloc()
|
||||
{
|
||||
for(int i = 1; i < 1000; i++)
|
||||
{
|
||||
ei_declare_aligned_stack_constructed_variable(float, p, i, 0);
|
||||
VERIFY(std::size_t(p)%ALIGNMENT==0);
|
||||
// if the buffer is wrongly allocated this will give a bad write --> check with valgrind
|
||||
for(int j = 0; j < i; j++) p[j]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test compilation with both a struct and a class...
|
||||
struct MyStruct
|
||||
{
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
char dummychar;
|
||||
Vector4f avec;
|
||||
};
|
||||
|
||||
class MyClassA
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
char dummychar;
|
||||
Vector4f avec;
|
||||
};
|
||||
|
||||
template<typename T> void check_dynaligned()
|
||||
{
|
||||
T* obj = new T;
|
||||
VERIFY(std::size_t(obj)%ALIGNMENT==0);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
void test_eigen2_dynalloc()
|
||||
{
|
||||
// low level dynamic memory allocation
|
||||
CALL_SUBTEST(check_handmade_aligned_malloc());
|
||||
CALL_SUBTEST(check_aligned_malloc());
|
||||
CALL_SUBTEST(check_aligned_new());
|
||||
CALL_SUBTEST(check_aligned_stack_alloc());
|
||||
|
||||
for (int i=0; i<g_repeat*100; ++i)
|
||||
{
|
||||
CALL_SUBTEST( check_dynaligned<Vector4f>() );
|
||||
CALL_SUBTEST( check_dynaligned<Vector2d>() );
|
||||
CALL_SUBTEST( check_dynaligned<Matrix4f>() );
|
||||
CALL_SUBTEST( check_dynaligned<Vector4d>() );
|
||||
CALL_SUBTEST( check_dynaligned<Vector4i>() );
|
||||
}
|
||||
|
||||
// check static allocation, who knows ?
|
||||
{
|
||||
MyStruct foo0; VERIFY(std::size_t(foo0.avec.data())%ALIGNMENT==0);
|
||||
MyClassA fooA; VERIFY(std::size_t(fooA.avec.data())%ALIGNMENT==0);
|
||||
}
|
||||
|
||||
// dynamic allocation, single object
|
||||
for (int i=0; i<g_repeat*100; ++i)
|
||||
{
|
||||
MyStruct *foo0 = new MyStruct(); VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
|
||||
MyClassA *fooA = new MyClassA(); VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
|
||||
delete foo0;
|
||||
delete fooA;
|
||||
}
|
||||
|
||||
// dynamic allocation, array
|
||||
const int N = 10;
|
||||
for (int i=0; i<g_repeat*100; ++i)
|
||||
{
|
||||
MyStruct *foo0 = new MyStruct[N]; VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
|
||||
MyClassA *fooA = new MyClassA[N]; VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
|
||||
delete[] foo0;
|
||||
delete[] fooA;
|
||||
}
|
||||
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/QR>
|
||||
|
||||
#ifdef HAS_GSL
|
||||
#include "gsl_helper.h"
|
||||
#endif
|
||||
|
||||
template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
|
||||
*/
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
|
||||
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
|
||||
|
||||
RealScalar largerEps = 10*test_precision<RealScalar>();
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
MatrixType a1 = MatrixType::Random(rows,cols);
|
||||
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
|
||||
|
||||
MatrixType b = MatrixType::Random(rows,cols);
|
||||
MatrixType b1 = MatrixType::Random(rows,cols);
|
||||
MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
|
||||
|
||||
SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
|
||||
// generalized eigen pb
|
||||
SelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);
|
||||
|
||||
#ifdef HAS_GSL
|
||||
if (ei_is_same_type<RealScalar,double>::ret)
|
||||
{
|
||||
typedef GslTraits<Scalar> Gsl;
|
||||
typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
|
||||
typename GslTraits<RealScalar>::Vector gEval=0;
|
||||
RealVectorType _eval;
|
||||
MatrixType _evec;
|
||||
convert<MatrixType>(symmA, gSymmA);
|
||||
convert<MatrixType>(symmB, gSymmB);
|
||||
convert<MatrixType>(symmA, gEvec);
|
||||
gEval = GslTraits<RealScalar>::createVector(rows);
|
||||
|
||||
Gsl::eigen_symm(gSymmA, gEval, gEvec);
|
||||
convert(gEval, _eval);
|
||||
convert(gEvec, _evec);
|
||||
|
||||
// test gsl itself !
|
||||
VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));
|
||||
|
||||
// compare with eigen
|
||||
VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
|
||||
VERIFY_IS_APPROX(_evec.cwise().abs(), eiSymm.eigenvectors().cwise().abs());
|
||||
|
||||
// generalized pb
|
||||
Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
|
||||
convert(gEval, _eval);
|
||||
convert(gEvec, _evec);
|
||||
// test GSL itself:
|
||||
VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));
|
||||
|
||||
// compare with eigen
|
||||
MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
|
||||
VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
|
||||
VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());
|
||||
|
||||
Gsl::free(gSymmA);
|
||||
Gsl::free(gSymmB);
|
||||
GslTraits<RealScalar>::free(gEval);
|
||||
Gsl::free(gEvec);
|
||||
}
|
||||
#endif
|
||||
|
||||
VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
|
||||
eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
|
||||
|
||||
// generalized eigen problem Ax = lBx
|
||||
VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
|
||||
symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
|
||||
|
||||
MatrixType sqrtSymmA = eiSymm.operatorSqrt();
|
||||
VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA);
|
||||
VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt());
|
||||
}
|
||||
|
||||
template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
EigenSolver.h
|
||||
*/
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
|
||||
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
|
||||
|
||||
// RealScalar largerEps = 10*test_precision<RealScalar>();
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
MatrixType a1 = MatrixType::Random(rows,cols);
|
||||
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
|
||||
|
||||
EigenSolver<MatrixType> ei0(symmA);
|
||||
VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
|
||||
VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
|
||||
(ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));
|
||||
|
||||
EigenSolver<MatrixType> ei1(a);
|
||||
VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
|
||||
VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
|
||||
ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
|
||||
|
||||
}
|
||||
|
||||
void test_eigen2_eigensolver()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
// very important to test a 3x3 matrix since we provide a special path for it
|
||||
CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
|
||||
CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
|
||||
CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(7,7)) );
|
||||
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXcd(5,5)) );
|
||||
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXd(19,19)) );
|
||||
|
||||
CALL_SUBTEST_6( eigensolver(Matrix4f()) );
|
||||
CALL_SUBTEST_5( eigensolver(MatrixXd(17,17)) );
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename Scalar>
|
||||
void test_eigen2_first_aligned_helper(Scalar *array, int size)
|
||||
{
|
||||
const int packet_size = sizeof(Scalar) * ei_packet_traits<Scalar>::size;
|
||||
VERIFY(((std::size_t(array) + sizeof(Scalar) * ei_alignmentOffset(array, size)) % packet_size) == 0);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void test_eigen2_none_aligned_helper(Scalar *array, int size)
|
||||
{
|
||||
VERIFY(ei_packet_traits<Scalar>::size == 1 || ei_alignmentOffset(array, size) == size);
|
||||
}
|
||||
|
||||
struct some_non_vectorizable_type { float x; };
|
||||
|
||||
void test_eigen2_first_aligned()
|
||||
{
|
||||
EIGEN_ALIGN_128 float array_float[100];
|
||||
test_first_aligned_helper(array_float, 50);
|
||||
test_first_aligned_helper(array_float+1, 50);
|
||||
test_first_aligned_helper(array_float+2, 50);
|
||||
test_first_aligned_helper(array_float+3, 50);
|
||||
test_first_aligned_helper(array_float+4, 50);
|
||||
test_first_aligned_helper(array_float+5, 50);
|
||||
|
||||
EIGEN_ALIGN_128 double array_double[100];
|
||||
test_first_aligned_helper(array_double, 50);
|
||||
test_first_aligned_helper(array_double+1, 50);
|
||||
test_first_aligned_helper(array_double+2, 50);
|
||||
|
||||
double *array_double_plus_4_bytes = (double*)(std::size_t(array_double)+4);
|
||||
test_none_aligned_helper(array_double_plus_4_bytes, 50);
|
||||
test_none_aligned_helper(array_double_plus_4_bytes+1, 50);
|
||||
|
||||
some_non_vectorizable_type array_nonvec[100];
|
||||
test_first_aligned_helper(array_nonvec, 100);
|
||||
test_none_aligned_helper(array_nonvec, 100);
|
||||
}
|
@ -1,431 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/SVD>
|
||||
|
||||
template<typename Scalar> void geometry(void)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Cross.h Quaternion.h, Transform.cpp
|
||||
*/
|
||||
|
||||
typedef Matrix<Scalar,2,2> Matrix2;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,4,4> Matrix4;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Matrix<Scalar,4,1> Vector4;
|
||||
typedef Quaternion<Scalar> Quaternionx;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
typedef Transform<Scalar,2> Transform2;
|
||||
typedef Transform<Scalar,3> Transform3;
|
||||
typedef Scaling<Scalar,2> Scaling2;
|
||||
typedef Scaling<Scalar,3> Scaling3;
|
||||
typedef Translation<Scalar,2> Translation2;
|
||||
typedef Translation<Scalar,3> Translation3;
|
||||
|
||||
Scalar largeEps = test_precision<Scalar>();
|
||||
if (ei_is_same_type<Scalar,float>::ret)
|
||||
largeEps = 1e-2f;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random(),
|
||||
v2 = Vector3::Random();
|
||||
Vector2 u0 = Vector2::Random();
|
||||
Matrix3 matrot1;
|
||||
|
||||
Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
|
||||
// cross product
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
|
||||
Matrix3 m;
|
||||
m << v0.normalized(),
|
||||
(v0.cross(v1)).normalized(),
|
||||
(v0.cross(v1).cross(v0)).normalized();
|
||||
VERIFY(m.isUnitary());
|
||||
|
||||
// Quaternion: Identity(), setIdentity();
|
||||
Quaternionx q1, q2;
|
||||
q2.setIdentity();
|
||||
VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
|
||||
q1.coeffs().setRandom();
|
||||
VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
|
||||
|
||||
// unitOrthogonal
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
|
||||
VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
|
||||
VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
|
||||
|
||||
|
||||
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
|
||||
VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
|
||||
VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
|
||||
m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
|
||||
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
|
||||
VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
|
||||
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
q2 = AngleAxisx(a, v1.normalized());
|
||||
|
||||
// angular distance
|
||||
Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
|
||||
if (refangle>Scalar(M_PI))
|
||||
refangle = Scalar(2)*Scalar(M_PI) - refangle;
|
||||
|
||||
if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
|
||||
{
|
||||
VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
|
||||
}
|
||||
|
||||
// rotation matrix conversion
|
||||
VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
|
||||
VERIFY_IS_APPROX(q1 * q2 * v2,
|
||||
q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
|
||||
|
||||
VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
|
||||
q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
|
||||
|
||||
q2 = q1.toRotationMatrix();
|
||||
VERIFY_IS_APPROX(q1*v1,q2*v1);
|
||||
|
||||
matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
|
||||
* AngleAxisx(Scalar(0.2), Vector3::UnitY())
|
||||
* AngleAxisx(Scalar(0.3), Vector3::UnitZ());
|
||||
VERIFY_IS_APPROX(matrot1 * v1,
|
||||
AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
|
||||
* (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
|
||||
* (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
|
||||
|
||||
// angle-axis conversion
|
||||
AngleAxisx aa = q1;
|
||||
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
|
||||
VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
|
||||
|
||||
// from two vector creation
|
||||
VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
|
||||
VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
|
||||
|
||||
// inverse and conjugate
|
||||
VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
|
||||
|
||||
// AngleAxis
|
||||
VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
|
||||
Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
|
||||
|
||||
AngleAxisx aa1;
|
||||
m = q1.toRotationMatrix();
|
||||
aa1 = m;
|
||||
VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
|
||||
Quaternionx(m).toRotationMatrix());
|
||||
|
||||
// Transform
|
||||
// TODO complete the tests !
|
||||
a = 0;
|
||||
while (ei_abs(a)<Scalar(0.1))
|
||||
a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
Transform3 t0, t1, t2;
|
||||
// first test setIdentity() and Identity()
|
||||
t0.setIdentity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
t0.matrix().setZero();
|
||||
t0 = Transform3::Identity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t1.setIdentity();
|
||||
t1.linear() = q1.toRotationMatrix();
|
||||
|
||||
v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
|
||||
t0.scale(v0);
|
||||
t1.prescale(v0);
|
||||
|
||||
VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
|
||||
//VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
|
||||
|
||||
t0.setIdentity();
|
||||
t1.setIdentity();
|
||||
v1 << 1, 2, 3;
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t0.pretranslate(v0);
|
||||
t0.scale(v1);
|
||||
t1.linear() = q1.conjugate().toRotationMatrix();
|
||||
t1.prescale(v1.cwise().inverse());
|
||||
t1.translate(-v0);
|
||||
|
||||
VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
|
||||
|
||||
t1.fromPositionOrientationScale(v0, q1, v1);
|
||||
VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
|
||||
VERIFY_IS_APPROX(t1*v1, t0*v1);
|
||||
|
||||
t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
|
||||
t1.setIdentity(); t1.scale(v0).rotate(q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
|
||||
VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
|
||||
|
||||
// More transform constructors, operator=, operator*=
|
||||
|
||||
Matrix3 mat3 = Matrix3::Random();
|
||||
Matrix4 mat4;
|
||||
mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
|
||||
Transform3 tmat3(mat3), tmat4(mat4);
|
||||
tmat4.matrix()(3,3) = Scalar(1);
|
||||
VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
|
||||
|
||||
Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
Vector3 v3 = Vector3::Random().normalized();
|
||||
AngleAxisx aa3(a3, v3);
|
||||
Transform3 t3(aa3);
|
||||
Transform3 t4;
|
||||
t4 = aa3;
|
||||
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
|
||||
t4.rotate(AngleAxisx(-a3,v3));
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= aa3;
|
||||
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
|
||||
|
||||
v3 = Vector3::Random();
|
||||
Translation3 tv3(v3);
|
||||
Transform3 t5(tv3);
|
||||
t4 = tv3;
|
||||
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
|
||||
t4.translate(-v3);
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= tv3;
|
||||
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
|
||||
|
||||
Scaling3 sv3(v3);
|
||||
Transform3 t6(sv3);
|
||||
t4 = sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
t4.scale(v3.cwise().inverse());
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
|
||||
// matrix * transform
|
||||
VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
|
||||
|
||||
// chained Transform product
|
||||
VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
|
||||
|
||||
// check that Transform product doesn't have aliasing problems
|
||||
t5 = t4;
|
||||
t5 = t5*t5;
|
||||
VERIFY_IS_APPROX(t5, t4*t4);
|
||||
|
||||
// 2D transformation
|
||||
Transform2 t20, t21;
|
||||
Vector2 v20 = Vector2::Random();
|
||||
Vector2 v21 = Vector2::Random();
|
||||
for (int k=0; k<2; ++k)
|
||||
if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
|
||||
t21.setIdentity();
|
||||
t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
|
||||
VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
|
||||
t21.pretranslate(v20).scale(v21).matrix());
|
||||
|
||||
t21.setIdentity();
|
||||
t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
|
||||
VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
|
||||
* (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
|
||||
|
||||
// Transform - new API
|
||||
// 3D
|
||||
t0.setIdentity();
|
||||
t0.rotate(q1).scale(v0).translate(v0);
|
||||
// mat * scaling and mat * translation
|
||||
t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// mat * transformation and scaling * translation
|
||||
t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.prerotate(q1).prescale(v0).pretranslate(v0);
|
||||
// translation * scaling and transformation * mat
|
||||
t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// scaling * mat and translation * mat
|
||||
t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.scale(v0).translate(v0).rotate(q1);
|
||||
// translation * mat and scaling * transformation
|
||||
t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * scaling
|
||||
t0.scale(v0);
|
||||
t1 = t1 * Scaling3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * translation
|
||||
t0.translate(v0);
|
||||
t1 = t1 * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// translation * transformation
|
||||
t0.pretranslate(v0);
|
||||
t1 = Translation3(v0) * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// transform * quaternion
|
||||
t0.rotate(q1);
|
||||
t1 = t1 * q1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// translation * quaternion
|
||||
t0.translate(v1).rotate(q1);
|
||||
t1 = t1 * (Translation3(v1) * q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// scaling * quaternion
|
||||
t0.scale(v1).rotate(q1);
|
||||
t1 = t1 * (Scaling3(v1) * q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * transform
|
||||
t0.prerotate(q1);
|
||||
t1 = q1 * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * translation
|
||||
t0.rotate(q1).translate(v1);
|
||||
t1 = t1 * (q1 * Translation3(v1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * scaling
|
||||
t0.rotate(q1).scale(v1);
|
||||
t1 = t1 * (q1 * Scaling3(v1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// translation * vector
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
|
||||
|
||||
// scaling * vector
|
||||
t0.setIdentity();
|
||||
t0.scale(v0);
|
||||
VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
|
||||
|
||||
// test transform inversion
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
t0.linear().setRandom();
|
||||
VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1);
|
||||
VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
|
||||
|
||||
// test extract rotation and scaling
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1).scale(v1);
|
||||
VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
|
||||
|
||||
Matrix3 mat_rotation, mat_scaling;
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1).scale(v1);
|
||||
t0.computeRotationScaling(&mat_rotation, &mat_scaling);
|
||||
VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
|
||||
VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
|
||||
VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
|
||||
t0.computeScalingRotation(&mat_scaling, &mat_rotation);
|
||||
VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
|
||||
VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
|
||||
VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
|
||||
|
||||
// test casting
|
||||
Transform<float,3> t1f = t1.template cast<float>();
|
||||
VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
|
||||
Transform<double,3> t1d = t1.template cast<double>();
|
||||
VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
|
||||
|
||||
Translation3 tr1(v0);
|
||||
Translation<float,3> tr1f = tr1.template cast<float>();
|
||||
VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
|
||||
Translation<double,3> tr1d = tr1.template cast<double>();
|
||||
VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
|
||||
|
||||
Scaling3 sc1(v0);
|
||||
Scaling<float,3> sc1f = sc1.template cast<float>();
|
||||
VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
|
||||
Scaling<double,3> sc1d = sc1.template cast<double>();
|
||||
VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
|
||||
|
||||
Quaternion<float> q1f = q1.template cast<float>();
|
||||
VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
|
||||
Quaternion<double> q1d = q1.template cast<double>();
|
||||
VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
|
||||
|
||||
AngleAxis<float> aa1f = aa1.template cast<float>();
|
||||
VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
|
||||
AngleAxis<double> aa1d = aa1.template cast<double>();
|
||||
VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
|
||||
|
||||
Rotation2D<Scalar> r2d1(ei_random<Scalar>());
|
||||
Rotation2D<float> r2d1f = r2d1.template cast<float>();
|
||||
VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
|
||||
Rotation2D<double> r2d1d = r2d1.template cast<double>();
|
||||
VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
|
||||
|
||||
m = q1;
|
||||
// m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
|
||||
// m.col(0) = Vector3(-1,0,0).normalized();
|
||||
// m.col(2) = m.col(0).cross(m.col(1));
|
||||
#define VERIFY_EULER(I,J,K, X,Y,Z) { \
|
||||
Vector3 ea = m.eulerAngles(I,J,K); \
|
||||
Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
|
||||
VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
|
||||
}
|
||||
VERIFY_EULER(0,1,2, X,Y,Z);
|
||||
VERIFY_EULER(0,1,0, X,Y,X);
|
||||
VERIFY_EULER(0,2,1, X,Z,Y);
|
||||
VERIFY_EULER(0,2,0, X,Z,X);
|
||||
|
||||
VERIFY_EULER(1,2,0, Y,Z,X);
|
||||
VERIFY_EULER(1,2,1, Y,Z,Y);
|
||||
VERIFY_EULER(1,0,2, Y,X,Z);
|
||||
VERIFY_EULER(1,0,1, Y,X,Y);
|
||||
|
||||
VERIFY_EULER(2,0,1, Z,X,Y);
|
||||
VERIFY_EULER(2,0,2, Z,X,Z);
|
||||
VERIFY_EULER(2,1,0, Z,Y,X);
|
||||
VERIFY_EULER(2,1,2, Z,Y,Z);
|
||||
|
||||
// colwise/rowwise cross product
|
||||
mat3.setRandom();
|
||||
Vector3 vec3 = Vector3::Random();
|
||||
Matrix3 mcross;
|
||||
int i = ei_random<int>(0,2);
|
||||
mcross = mat3.colwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
|
||||
mcross = mat3.rowwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void test_eigen2_geometry()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( geometry<float>() );
|
||||
CALL_SUBTEST_2( geometry<double>() );
|
||||
}
|
||||
}
|
@ -1,434 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN2_SUPPORT_STAGE15_RESOLVE_API_CONFLICTS_WARN
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/SVD>
|
||||
|
||||
template<typename Scalar> void geometry(void)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Cross.h Quaternion.h, Transform.cpp
|
||||
*/
|
||||
|
||||
typedef Matrix<Scalar,2,2> Matrix2;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,4,4> Matrix4;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Matrix<Scalar,4,1> Vector4;
|
||||
typedef eigen2_Quaternion<Scalar> Quaternionx;
|
||||
typedef eigen2_AngleAxis<Scalar> AngleAxisx;
|
||||
typedef eigen2_Transform<Scalar,2> Transform2;
|
||||
typedef eigen2_Transform<Scalar,3> Transform3;
|
||||
typedef eigen2_Scaling<Scalar,2> Scaling2;
|
||||
typedef eigen2_Scaling<Scalar,3> Scaling3;
|
||||
typedef eigen2_Translation<Scalar,2> Translation2;
|
||||
typedef eigen2_Translation<Scalar,3> Translation3;
|
||||
|
||||
Scalar largeEps = test_precision<Scalar>();
|
||||
if (ei_is_same_type<Scalar,float>::ret)
|
||||
largeEps = 1e-2f;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random(),
|
||||
v2 = Vector3::Random();
|
||||
Vector2 u0 = Vector2::Random();
|
||||
Matrix3 matrot1;
|
||||
|
||||
Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
|
||||
// cross product
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
|
||||
Matrix3 m;
|
||||
m << v0.normalized(),
|
||||
(v0.cross(v1)).normalized(),
|
||||
(v0.cross(v1).cross(v0)).normalized();
|
||||
VERIFY(m.isUnitary());
|
||||
|
||||
// Quaternion: Identity(), setIdentity();
|
||||
Quaternionx q1, q2;
|
||||
q2.setIdentity();
|
||||
VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
|
||||
q1.coeffs().setRandom();
|
||||
VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
|
||||
|
||||
// unitOrthogonal
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
|
||||
VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
|
||||
VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
|
||||
|
||||
|
||||
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
|
||||
VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
|
||||
VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
|
||||
m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
|
||||
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
|
||||
VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
|
||||
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
q2 = AngleAxisx(a, v1.normalized());
|
||||
|
||||
// angular distance
|
||||
Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
|
||||
if (refangle>Scalar(M_PI))
|
||||
refangle = Scalar(2)*Scalar(M_PI) - refangle;
|
||||
|
||||
if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
|
||||
{
|
||||
VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
|
||||
}
|
||||
|
||||
// rotation matrix conversion
|
||||
VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
|
||||
VERIFY_IS_APPROX(q1 * q2 * v2,
|
||||
q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
|
||||
|
||||
VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
|
||||
q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
|
||||
|
||||
q2 = q1.toRotationMatrix();
|
||||
VERIFY_IS_APPROX(q1*v1,q2*v1);
|
||||
|
||||
matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
|
||||
* AngleAxisx(Scalar(0.2), Vector3::UnitY())
|
||||
* AngleAxisx(Scalar(0.3), Vector3::UnitZ());
|
||||
VERIFY_IS_APPROX(matrot1 * v1,
|
||||
AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
|
||||
* (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
|
||||
* (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
|
||||
|
||||
// angle-axis conversion
|
||||
AngleAxisx aa = q1;
|
||||
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
|
||||
VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
|
||||
|
||||
// from two vector creation
|
||||
VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
|
||||
VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
|
||||
|
||||
// inverse and conjugate
|
||||
VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
|
||||
|
||||
// AngleAxis
|
||||
VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
|
||||
Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
|
||||
|
||||
AngleAxisx aa1;
|
||||
m = q1.toRotationMatrix();
|
||||
aa1 = m;
|
||||
VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
|
||||
Quaternionx(m).toRotationMatrix());
|
||||
|
||||
// Transform
|
||||
// TODO complete the tests !
|
||||
a = 0;
|
||||
while (ei_abs(a)<Scalar(0.1))
|
||||
a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
Transform3 t0, t1, t2;
|
||||
// first test setIdentity() and Identity()
|
||||
t0.setIdentity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
t0.matrix().setZero();
|
||||
t0 = Transform3::Identity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t1.setIdentity();
|
||||
t1.linear() = q1.toRotationMatrix();
|
||||
|
||||
v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
|
||||
t0.scale(v0);
|
||||
t1.prescale(v0);
|
||||
|
||||
VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
|
||||
//VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
|
||||
|
||||
t0.setIdentity();
|
||||
t1.setIdentity();
|
||||
v1 << 1, 2, 3;
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t0.pretranslate(v0);
|
||||
t0.scale(v1);
|
||||
t1.linear() = q1.conjugate().toRotationMatrix();
|
||||
t1.prescale(v1.cwise().inverse());
|
||||
t1.translate(-v0);
|
||||
|
||||
VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
|
||||
|
||||
t1.fromPositionOrientationScale(v0, q1, v1);
|
||||
VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
|
||||
VERIFY_IS_APPROX(t1*v1, t0*v1);
|
||||
|
||||
t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
|
||||
t1.setIdentity(); t1.scale(v0).rotate(q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
|
||||
VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
|
||||
|
||||
// More transform constructors, operator=, operator*=
|
||||
|
||||
Matrix3 mat3 = Matrix3::Random();
|
||||
Matrix4 mat4;
|
||||
mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
|
||||
Transform3 tmat3(mat3), tmat4(mat4);
|
||||
tmat4.matrix()(3,3) = Scalar(1);
|
||||
VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
|
||||
|
||||
Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
Vector3 v3 = Vector3::Random().normalized();
|
||||
AngleAxisx aa3(a3, v3);
|
||||
Transform3 t3(aa3);
|
||||
Transform3 t4;
|
||||
t4 = aa3;
|
||||
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
|
||||
t4.rotate(AngleAxisx(-a3,v3));
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= aa3;
|
||||
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
|
||||
|
||||
v3 = Vector3::Random();
|
||||
Translation3 tv3(v3);
|
||||
Transform3 t5(tv3);
|
||||
t4 = tv3;
|
||||
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
|
||||
t4.translate(-v3);
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= tv3;
|
||||
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
|
||||
|
||||
Scaling3 sv3(v3);
|
||||
Transform3 t6(sv3);
|
||||
t4 = sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
t4.scale(v3.cwise().inverse());
|
||||
VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
|
||||
t4 *= sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
|
||||
// matrix * transform
|
||||
VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
|
||||
|
||||
// chained Transform product
|
||||
VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
|
||||
|
||||
// check that Transform product doesn't have aliasing problems
|
||||
t5 = t4;
|
||||
t5 = t5*t5;
|
||||
VERIFY_IS_APPROX(t5, t4*t4);
|
||||
|
||||
// 2D transformation
|
||||
Transform2 t20, t21;
|
||||
Vector2 v20 = Vector2::Random();
|
||||
Vector2 v21 = Vector2::Random();
|
||||
for (int k=0; k<2; ++k)
|
||||
if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
|
||||
t21.setIdentity();
|
||||
t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
|
||||
VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
|
||||
t21.pretranslate(v20).scale(v21).matrix());
|
||||
|
||||
t21.setIdentity();
|
||||
t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
|
||||
VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
|
||||
* (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
|
||||
|
||||
// Transform - new API
|
||||
// 3D
|
||||
t0.setIdentity();
|
||||
t0.rotate(q1).scale(v0).translate(v0);
|
||||
// mat * scaling and mat * translation
|
||||
t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// mat * transformation and scaling * translation
|
||||
t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.prerotate(q1).prescale(v0).pretranslate(v0);
|
||||
// translation * scaling and transformation * mat
|
||||
t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// scaling * mat and translation * mat
|
||||
t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.scale(v0).translate(v0).rotate(q1);
|
||||
// translation * mat and scaling * transformation
|
||||
t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * scaling
|
||||
t0.scale(v0);
|
||||
t1 = t1 * Scaling3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * translation
|
||||
t0.translate(v0);
|
||||
t1 = t1 * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// translation * transformation
|
||||
t0.pretranslate(v0);
|
||||
t1 = Translation3(v0) * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// transform * quaternion
|
||||
t0.rotate(q1);
|
||||
t1 = t1 * q1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// translation * quaternion
|
||||
t0.translate(v1).rotate(q1);
|
||||
t1 = t1 * (Translation3(v1) * q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// scaling * quaternion
|
||||
t0.scale(v1).rotate(q1);
|
||||
t1 = t1 * (Scaling3(v1) * q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * transform
|
||||
t0.prerotate(q1);
|
||||
t1 = q1 * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * translation
|
||||
t0.rotate(q1).translate(v1);
|
||||
t1 = t1 * (q1 * Translation3(v1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// quaternion * scaling
|
||||
t0.rotate(q1).scale(v1);
|
||||
t1 = t1 * (q1 * Scaling3(v1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// translation * vector
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
|
||||
|
||||
// scaling * vector
|
||||
t0.setIdentity();
|
||||
t0.scale(v0);
|
||||
VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
|
||||
|
||||
// test transform inversion
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
t0.linear().setRandom();
|
||||
VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1);
|
||||
VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
|
||||
|
||||
// test extract rotation and scaling
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1).scale(v1);
|
||||
VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
|
||||
|
||||
Matrix3 mat_rotation, mat_scaling;
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1).scale(v1);
|
||||
t0.computeRotationScaling(&mat_rotation, &mat_scaling);
|
||||
VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
|
||||
VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
|
||||
VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
|
||||
t0.computeScalingRotation(&mat_scaling, &mat_rotation);
|
||||
VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
|
||||
VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
|
||||
VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
|
||||
|
||||
// test casting
|
||||
eigen2_Transform<float,3> t1f = t1.template cast<float>();
|
||||
VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
|
||||
eigen2_Transform<double,3> t1d = t1.template cast<double>();
|
||||
VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
|
||||
|
||||
Translation3 tr1(v0);
|
||||
eigen2_Translation<float,3> tr1f = tr1.template cast<float>();
|
||||
VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
|
||||
eigen2_Translation<double,3> tr1d = tr1.template cast<double>();
|
||||
VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
|
||||
|
||||
Scaling3 sc1(v0);
|
||||
eigen2_Scaling<float,3> sc1f = sc1.template cast<float>();
|
||||
VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
|
||||
eigen2_Scaling<double,3> sc1d = sc1.template cast<double>();
|
||||
VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
|
||||
|
||||
eigen2_Quaternion<float> q1f = q1.template cast<float>();
|
||||
VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
|
||||
eigen2_Quaternion<double> q1d = q1.template cast<double>();
|
||||
VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
|
||||
|
||||
eigen2_AngleAxis<float> aa1f = aa1.template cast<float>();
|
||||
VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
|
||||
eigen2_AngleAxis<double> aa1d = aa1.template cast<double>();
|
||||
VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
|
||||
|
||||
eigen2_Rotation2D<Scalar> r2d1(ei_random<Scalar>());
|
||||
eigen2_Rotation2D<float> r2d1f = r2d1.template cast<float>();
|
||||
VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
|
||||
eigen2_Rotation2D<double> r2d1d = r2d1.template cast<double>();
|
||||
VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
|
||||
|
||||
m = q1;
|
||||
// m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
|
||||
// m.col(0) = Vector3(-1,0,0).normalized();
|
||||
// m.col(2) = m.col(0).cross(m.col(1));
|
||||
#define VERIFY_EULER(I,J,K, X,Y,Z) { \
|
||||
Vector3 ea = m.eulerAngles(I,J,K); \
|
||||
Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
|
||||
VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
|
||||
}
|
||||
VERIFY_EULER(0,1,2, X,Y,Z);
|
||||
VERIFY_EULER(0,1,0, X,Y,X);
|
||||
VERIFY_EULER(0,2,1, X,Z,Y);
|
||||
VERIFY_EULER(0,2,0, X,Z,X);
|
||||
|
||||
VERIFY_EULER(1,2,0, Y,Z,X);
|
||||
VERIFY_EULER(1,2,1, Y,Z,Y);
|
||||
VERIFY_EULER(1,0,2, Y,X,Z);
|
||||
VERIFY_EULER(1,0,1, Y,X,Y);
|
||||
|
||||
VERIFY_EULER(2,0,1, Z,X,Y);
|
||||
VERIFY_EULER(2,0,2, Z,X,Z);
|
||||
VERIFY_EULER(2,1,0, Z,Y,X);
|
||||
VERIFY_EULER(2,1,2, Z,Y,Z);
|
||||
|
||||
// colwise/rowwise cross product
|
||||
mat3.setRandom();
|
||||
Vector3 vec3 = Vector3::Random();
|
||||
Matrix3 mcross;
|
||||
int i = ei_random<int>(0,2);
|
||||
mcross = mat3.colwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
|
||||
mcross = mat3.rowwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void test_eigen2_geometry_with_eigen2_prefix()
|
||||
{
|
||||
std::cout << "eigen2 support: " << EIGEN2_SUPPORT_STAGE << std::endl;
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( geometry<float>() );
|
||||
CALL_SUBTEST_2( geometry<double>() );
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Hyperplane.h
|
||||
*/
|
||||
|
||||
const int dim = _plane.dim();
|
||||
typedef typename HyperplaneType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
|
||||
HyperplaneType::AmbientDimAtCompileTime> MatrixType;
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
|
||||
VectorType n0 = VectorType::Random(dim).normalized();
|
||||
VectorType n1 = VectorType::Random(dim).normalized();
|
||||
|
||||
HyperplaneType pl0(n0, p0);
|
||||
HyperplaneType pl1(n1, p1);
|
||||
HyperplaneType pl2 = pl1;
|
||||
|
||||
Scalar s0 = ei_random<Scalar>();
|
||||
Scalar s1 = ei_random<Scalar>();
|
||||
|
||||
VERIFY_IS_APPROX( n1.eigen2_dot(n1), Scalar(1) );
|
||||
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
|
||||
VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 + pl1.normal().unitOrthogonal() * s1), Scalar(1) );
|
||||
|
||||
// transform
|
||||
if (!NumTraits<Scalar>::IsComplex)
|
||||
{
|
||||
MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ();
|
||||
Scaling<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
|
||||
Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
|
||||
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
|
||||
.absDistance((rot*scaling*translation) * p1), Scalar(1) );
|
||||
pl2 = pl1;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
|
||||
.absDistance((rot*translation) * p1), Scalar(1) );
|
||||
}
|
||||
|
||||
// casting
|
||||
const int Dim = HyperplaneType::AmbientDimAtCompileTime;
|
||||
typedef typename GetDifferentType<Scalar>::type OtherScalar;
|
||||
Hyperplane<OtherScalar,Dim> hp1f = pl1.template cast<OtherScalar>();
|
||||
VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
|
||||
Hyperplane<Scalar,Dim> hp1d = pl1.template cast<Scalar>();
|
||||
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
|
||||
}
|
||||
|
||||
template<typename Scalar> void lines()
|
||||
{
|
||||
typedef Hyperplane<Scalar, 2> HLine;
|
||||
typedef ParametrizedLine<Scalar, 2> PLine;
|
||||
typedef Matrix<Scalar,2,1> Vector;
|
||||
typedef Matrix<Scalar,3,1> CoeffsType;
|
||||
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
Vector center = Vector::Random();
|
||||
Vector u = Vector::Random();
|
||||
Vector v = Vector::Random();
|
||||
Scalar a = ei_random<Scalar>();
|
||||
while (ei_abs(a-1) < 1e-4) a = ei_random<Scalar>();
|
||||
while (u.norm() < 1e-4) u = Vector::Random();
|
||||
while (v.norm() < 1e-4) v = Vector::Random();
|
||||
|
||||
HLine line_u = HLine::Through(center + u, center + a*u);
|
||||
HLine line_v = HLine::Through(center + v, center + a*v);
|
||||
|
||||
// the line equations should be normalized so that a^2+b^2=1
|
||||
VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
|
||||
VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
|
||||
|
||||
Vector result = line_u.intersection(line_v);
|
||||
|
||||
// the lines should intersect at the point we called "center"
|
||||
VERIFY_IS_APPROX(result, center);
|
||||
|
||||
// check conversions between two types of lines
|
||||
PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
|
||||
CoeffsType converted_coeffs(HLine(pl).coeffs());
|
||||
converted_coeffs *= line_u.coeffs()(0)/converted_coeffs(0);
|
||||
VERIFY(line_u.coeffs().isApprox(converted_coeffs));
|
||||
}
|
||||
}
|
||||
|
||||
void test_eigen2_hyperplane()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
|
||||
CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
|
||||
CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
|
||||
CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
|
||||
CALL_SUBTEST_5( lines<float>() );
|
||||
CALL_SUBTEST_6( lines<double>() );
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
|
||||
template<typename MatrixType> void inverse(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Inverse.h
|
||||
*/
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = MatrixType::Identity(rows, rows);
|
||||
|
||||
while(ei_abs(m1.determinant()) < RealScalar(0.1) && rows <= 8)
|
||||
{
|
||||
m1 = MatrixType::Random(rows, cols);
|
||||
}
|
||||
|
||||
m2 = m1.inverse();
|
||||
VERIFY_IS_APPROX(m1, m2.inverse() );
|
||||
|
||||
m1.computeInverse(&m2);
|
||||
VERIFY_IS_APPROX(m1, m2.inverse() );
|
||||
|
||||
VERIFY_IS_APPROX((Scalar(2)*m2).inverse(), m2.inverse()*Scalar(0.5));
|
||||
|
||||
VERIFY_IS_APPROX(identity, m1.inverse() * m1 );
|
||||
VERIFY_IS_APPROX(identity, m1 * m1.inverse() );
|
||||
|
||||
VERIFY_IS_APPROX(m1, m1.inverse().inverse() );
|
||||
|
||||
// since for the general case we implement separately row-major and col-major, test that
|
||||
VERIFY_IS_APPROX(m1.transpose().inverse(), m1.inverse().transpose());
|
||||
}
|
||||
|
||||
void test_eigen2_inverse()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_2( inverse(Matrix2d()) );
|
||||
CALL_SUBTEST_3( inverse(Matrix3f()) );
|
||||
CALL_SUBTEST_4( inverse(Matrix4f()) );
|
||||
CALL_SUBTEST_5( inverse(MatrixXf(8,8)) );
|
||||
CALL_SUBTEST_6( inverse(MatrixXcd(7,7)) );
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void linearStructure(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Sum.h Difference.h Opposite.h ScalarMultiple.h
|
||||
*/
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
// this test relies a lot on Random.h, and there's not much more that we can do
|
||||
// to test it, hence I consider that we will have tested Random.h
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols);
|
||||
|
||||
Scalar s1 = ei_random<Scalar>();
|
||||
while (ei_abs(s1)<1e-3) s1 = ei_random<Scalar>();
|
||||
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
|
||||
VERIFY_IS_APPROX(-(-m1), m1);
|
||||
VERIFY_IS_APPROX(m1+m1, 2*m1);
|
||||
VERIFY_IS_APPROX(m1+m2-m1, m2);
|
||||
VERIFY_IS_APPROX(-m2+m1+m2, m1);
|
||||
VERIFY_IS_APPROX(m1*s1, s1*m1);
|
||||
VERIFY_IS_APPROX((m1+m2)*s1, s1*m1+s1*m2);
|
||||
VERIFY_IS_APPROX((-m1+m2)*s1, -s1*m1+s1*m2);
|
||||
m3 = m2; m3 += m1;
|
||||
VERIFY_IS_APPROX(m3, m1+m2);
|
||||
m3 = m2; m3 -= m1;
|
||||
VERIFY_IS_APPROX(m3, m2-m1);
|
||||
m3 = m2; m3 *= s1;
|
||||
VERIFY_IS_APPROX(m3, s1*m2);
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
{
|
||||
m3 = m2; m3 /= s1;
|
||||
VERIFY_IS_APPROX(m3, m2/s1);
|
||||
}
|
||||
|
||||
// again, test operator() to check const-qualification
|
||||
VERIFY_IS_APPROX((-m1)(r,c), -(m1(r,c)));
|
||||
VERIFY_IS_APPROX((m1-m2)(r,c), (m1(r,c))-(m2(r,c)));
|
||||
VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
|
||||
VERIFY_IS_APPROX((s1*m1)(r,c), s1*(m1(r,c)));
|
||||
VERIFY_IS_APPROX((m1*s1)(r,c), (m1(r,c))*s1);
|
||||
if(NumTraits<Scalar>::HasFloatingPoint)
|
||||
VERIFY_IS_APPROX((m1/s1)(r,c), (m1(r,c))/s1);
|
||||
|
||||
// use .block to disable vectorization and compare to the vectorized version
|
||||
VERIFY_IS_APPROX(m1+m1.block(0,0,rows,cols), m1+m1);
|
||||
VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
|
||||
VERIFY_IS_APPROX(m1 - m1.block(0,0,rows,cols), m1 - m1);
|
||||
VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
|
||||
}
|
||||
|
||||
void test_eigen2_linearstructure()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( linearStructure(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( linearStructure(Matrix2f()) );
|
||||
CALL_SUBTEST_3( linearStructure(Vector3d()) );
|
||||
CALL_SUBTEST_4( linearStructure(Matrix4d()) );
|
||||
CALL_SUBTEST_5( linearStructure(MatrixXcf(3, 3)) );
|
||||
CALL_SUBTEST_6( linearStructure(MatrixXf(8, 12)) );
|
||||
CALL_SUBTEST_7( linearStructure(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST_8( linearStructure(MatrixXcd(20, 20)) );
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
|
||||
template<typename Derived>
|
||||
void doSomeRankPreservingOperations(Eigen::MatrixBase<Derived>& m)
|
||||
{
|
||||
typedef typename Derived::RealScalar RealScalar;
|
||||
for(int a = 0; a < 3*(m.rows()+m.cols()); a++)
|
||||
{
|
||||
RealScalar d = Eigen::ei_random<RealScalar>(-1,1);
|
||||
int i = Eigen::ei_random<int>(0,m.rows()-1); // i is a random row number
|
||||
int j;
|
||||
do {
|
||||
j = Eigen::ei_random<int>(0,m.rows()-1);
|
||||
} while (i==j); // j is another one (must be different)
|
||||
m.row(i) += d * m.row(j);
|
||||
|
||||
i = Eigen::ei_random<int>(0,m.cols()-1); // i is a random column number
|
||||
do {
|
||||
j = Eigen::ei_random<int>(0,m.cols()-1);
|
||||
} while (i==j); // j is another one (must be different)
|
||||
m.col(i) += d * m.col(j);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void lu_non_invertible()
|
||||
{
|
||||
/* this test covers the following files:
|
||||
LU.h
|
||||
*/
|
||||
// NOTE there seems to be a problem with too small sizes -- could easily lie in the doSomeRankPreservingOperations function
|
||||
int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200);
|
||||
int rank = ei_random<int>(1, std::min(rows, cols)-1);
|
||||
|
||||
MatrixType m1(rows, cols), m2(cols, cols2), m3(rows, cols2), k(1,1);
|
||||
m1 = MatrixType::Random(rows,cols);
|
||||
if(rows <= cols)
|
||||
for(int i = rank; i < rows; i++) m1.row(i).setZero();
|
||||
else
|
||||
for(int i = rank; i < cols; i++) m1.col(i).setZero();
|
||||
doSomeRankPreservingOperations(m1);
|
||||
|
||||
LU<MatrixType> lu(m1);
|
||||
typename LU<MatrixType>::KernelResultType m1kernel = lu.kernel();
|
||||
typename LU<MatrixType>::ImageResultType m1image = lu.image();
|
||||
|
||||
VERIFY(rank == lu.rank());
|
||||
VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
|
||||
VERIFY(!lu.isInjective());
|
||||
VERIFY(!lu.isInvertible());
|
||||
VERIFY(lu.isSurjective() == (lu.rank() == rows));
|
||||
VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
|
||||
VERIFY(m1image.lu().rank() == rank);
|
||||
MatrixType sidebyside(m1.rows(), m1.cols() + m1image.cols());
|
||||
sidebyside << m1, m1image;
|
||||
VERIFY(sidebyside.lu().rank() == rank);
|
||||
m2 = MatrixType::Random(cols,cols2);
|
||||
m3 = m1*m2;
|
||||
m2 = MatrixType::Random(cols,cols2);
|
||||
lu.solve(m3, &m2);
|
||||
VERIFY_IS_APPROX(m3, m1*m2);
|
||||
/* solve now always returns true
|
||||
m3 = MatrixType::Random(rows,cols2);
|
||||
VERIFY(!lu.solve(m3, &m2));
|
||||
*/
|
||||
}
|
||||
|
||||
template<typename MatrixType> void lu_invertible()
|
||||
{
|
||||
/* this test covers the following files:
|
||||
LU.h
|
||||
*/
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
int size = ei_random<int>(10,200);
|
||||
|
||||
MatrixType m1(size, size), m2(size, size), m3(size, size);
|
||||
m1 = MatrixType::Random(size,size);
|
||||
|
||||
if (ei_is_same_type<RealScalar,float>::ret)
|
||||
{
|
||||
// let's build a matrix more stable to inverse
|
||||
MatrixType a = MatrixType::Random(size,size*2);
|
||||
m1 += a * a.adjoint();
|
||||
}
|
||||
|
||||
LU<MatrixType> lu(m1);
|
||||
VERIFY(0 == lu.dimensionOfKernel());
|
||||
VERIFY(size == lu.rank());
|
||||
VERIFY(lu.isInjective());
|
||||
VERIFY(lu.isSurjective());
|
||||
VERIFY(lu.isInvertible());
|
||||
VERIFY(lu.image().lu().isInvertible());
|
||||
m3 = MatrixType::Random(size,size);
|
||||
lu.solve(m3, &m2);
|
||||
VERIFY_IS_APPROX(m3, m1*m2);
|
||||
VERIFY_IS_APPROX(m2, lu.inverse()*m3);
|
||||
m3 = MatrixType::Random(size,size);
|
||||
VERIFY(lu.solve(m3, &m2));
|
||||
}
|
||||
|
||||
void test_eigen2_lu()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( lu_non_invertible<MatrixXf>() );
|
||||
CALL_SUBTEST_2( lu_non_invertible<MatrixXd>() );
|
||||
CALL_SUBTEST_3( lu_non_invertible<MatrixXcf>() );
|
||||
CALL_SUBTEST_4( lu_non_invertible<MatrixXcd>() );
|
||||
CALL_SUBTEST_1( lu_invertible<MatrixXf>() );
|
||||
CALL_SUBTEST_2( lu_invertible<MatrixXd>() );
|
||||
CALL_SUBTEST_3( lu_invertible<MatrixXcf>() );
|
||||
CALL_SUBTEST_4( lu_invertible<MatrixXcd>() );
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename VectorType> void map_class_vector(const VectorType& m)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
int size = m.size();
|
||||
|
||||
// test Map.h
|
||||
Scalar* array1 = ei_aligned_new<Scalar>(size);
|
||||
Scalar* array2 = ei_aligned_new<Scalar>(size);
|
||||
Scalar* array3 = new Scalar[size+1];
|
||||
Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
|
||||
|
||||
Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
|
||||
Map<VectorType>(array2, size) = Map<VectorType>(array1, size);
|
||||
Map<VectorType>(array3unaligned, size) = Map<VectorType>((const Scalar*)array1, size); // test non-const-correctness support in eigen2
|
||||
VectorType ma1 = Map<VectorType>(array1, size);
|
||||
VectorType ma2 = Map<VectorType, Aligned>(array2, size);
|
||||
VectorType ma3 = Map<VectorType>(array3unaligned, size);
|
||||
VERIFY_IS_APPROX(ma1, ma2);
|
||||
VERIFY_IS_APPROX(ma1, ma3);
|
||||
|
||||
ei_aligned_delete(array1, size);
|
||||
ei_aligned_delete(array2, size);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
template<typename MatrixType> void map_class_matrix(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
int rows = m.rows(), cols = m.cols(), size = rows*cols;
|
||||
|
||||
// test Map.h
|
||||
Scalar* array1 = ei_aligned_new<Scalar>(size);
|
||||
for(int i = 0; i < size; i++) array1[i] = Scalar(1);
|
||||
Scalar* array2 = ei_aligned_new<Scalar>(size);
|
||||
for(int i = 0; i < size; i++) array2[i] = Scalar(1);
|
||||
Scalar* array3 = new Scalar[size+1];
|
||||
for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
|
||||
Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
|
||||
Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
|
||||
Map<MatrixType>(array2, rows, cols) = Map<MatrixType>((const Scalar*)array1, rows, cols); // test non-const-correctness support in eigen2
|
||||
Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
|
||||
MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
|
||||
MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
|
||||
VERIFY_IS_APPROX(ma1, ma2);
|
||||
MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
|
||||
VERIFY_IS_APPROX(ma1, ma3);
|
||||
|
||||
ei_aligned_delete(array1, size);
|
||||
ei_aligned_delete(array2, size);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
template<typename VectorType> void map_static_methods(const VectorType& m)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
int size = m.size();
|
||||
|
||||
// test Map.h
|
||||
Scalar* array1 = ei_aligned_new<Scalar>(size);
|
||||
Scalar* array2 = ei_aligned_new<Scalar>(size);
|
||||
Scalar* array3 = new Scalar[size+1];
|
||||
Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
|
||||
|
||||
VectorType::MapAligned(array1, size) = VectorType::Random(size);
|
||||
VectorType::Map(array2, size) = VectorType::Map(array1, size);
|
||||
VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
|
||||
VectorType ma1 = VectorType::Map(array1, size);
|
||||
VectorType ma2 = VectorType::MapAligned(array2, size);
|
||||
VectorType ma3 = VectorType::Map(array3unaligned, size);
|
||||
VERIFY_IS_APPROX(ma1, ma2);
|
||||
VERIFY_IS_APPROX(ma1, ma3);
|
||||
|
||||
ei_aligned_delete(array1, size);
|
||||
ei_aligned_delete(array2, size);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
|
||||
void test_eigen2_map()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_class_vector(Vector4d()) );
|
||||
CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
|
||||
CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
|
||||
CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );
|
||||
|
||||
CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
|
||||
CALL_SUBTEST_6( map_class_matrix(Matrix<float,3,5>()) );
|
||||
CALL_SUBTEST_4( map_class_matrix(MatrixXcf(ei_random<int>(1,10),ei_random<int>(1,10))) );
|
||||
CALL_SUBTEST_5( map_class_matrix(MatrixXi(ei_random<int>(1,10),ei_random<int>(1,10))) );
|
||||
|
||||
CALL_SUBTEST_1( map_static_methods(Matrix<double, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_static_methods(Vector3f()) );
|
||||
CALL_SUBTEST_7( map_static_methods(RowVector3d()) );
|
||||
CALL_SUBTEST_4( map_static_methods(VectorXcd(8)) );
|
||||
CALL_SUBTEST_5( map_static_methods(VectorXf(12)) );
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
void test_eigen2_meta()
|
||||
{
|
||||
typedef float & FloatRef;
|
||||
typedef const float & ConstFloatRef;
|
||||
|
||||
VERIFY((ei_meta_if<(3<4),ei_meta_true, ei_meta_false>::ret::ret));
|
||||
VERIFY(( ei_is_same_type<float,float>::ret));
|
||||
VERIFY((!ei_is_same_type<float,double>::ret));
|
||||
VERIFY((!ei_is_same_type<float,float&>::ret));
|
||||
VERIFY((!ei_is_same_type<float,const float&>::ret));
|
||||
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<const float&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<const float*>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<const float*&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<float**>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<float**&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<float* const *&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_cleantype<float* const>::type >::ret));
|
||||
|
||||
VERIFY(( ei_is_same_type<float*,ei_unconst<const float*>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float&,ei_unconst<const float&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float&,ei_unconst<ConstFloatRef>::type >::ret));
|
||||
|
||||
VERIFY(( ei_is_same_type<float&,ei_unconst<float&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_unref<float&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<const float,ei_unref<const float&>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_unpointer<float*>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<const float,ei_unpointer<const float*>::type >::ret));
|
||||
VERIFY(( ei_is_same_type<float,ei_unpointer<float* const >::type >::ret));
|
||||
|
||||
VERIFY(ei_meta_sqrt<1>::ret == 1);
|
||||
#define VERIFY_META_SQRT(X) VERIFY(ei_meta_sqrt<X>::ret == int(ei_sqrt(double(X))))
|
||||
VERIFY_META_SQRT(2);
|
||||
VERIFY_META_SQRT(3);
|
||||
VERIFY_META_SQRT(4);
|
||||
VERIFY_META_SQRT(5);
|
||||
VERIFY_META_SQRT(6);
|
||||
VERIFY_META_SQRT(8);
|
||||
VERIFY_META_SQRT(9);
|
||||
VERIFY_META_SQRT(15);
|
||||
VERIFY_META_SQRT(16);
|
||||
VERIFY_META_SQRT(17);
|
||||
VERIFY_META_SQRT(255);
|
||||
VERIFY_META_SQRT(256);
|
||||
VERIFY_META_SQRT(257);
|
||||
VERIFY_META_SQRT(1023);
|
||||
VERIFY_META_SQRT(1024);
|
||||
VERIFY_META_SQRT(1025);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void miscMatrices(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
DiagonalMatrix.h Ones.h
|
||||
*/
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
int r = ei_random<int>(0, rows-1), r2 = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1);
|
||||
VERIFY_IS_APPROX(MatrixType::Ones(rows,cols)(r,c), static_cast<Scalar>(1));
|
||||
MatrixType m1 = MatrixType::Ones(rows,cols);
|
||||
VERIFY_IS_APPROX(m1(r,c), static_cast<Scalar>(1));
|
||||
VectorType v1 = VectorType::Random(rows);
|
||||
v1[0];
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
square = v1.asDiagonal();
|
||||
if(r==r2) VERIFY_IS_APPROX(square(r,r2), v1[r]);
|
||||
else VERIFY_IS_MUCH_SMALLER_THAN(square(r,r2), static_cast<Scalar>(1));
|
||||
square = MatrixType::Zero(rows, rows);
|
||||
square.diagonal() = VectorType::Ones(rows);
|
||||
VERIFY_IS_APPROX(square, MatrixType::Identity(rows, rows));
|
||||
}
|
||||
|
||||
void test_eigen2_miscmatrices()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( miscMatrices(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( miscMatrices(Matrix4d()) );
|
||||
CALL_SUBTEST_3( miscMatrices(MatrixXcf(3, 3)) );
|
||||
CALL_SUBTEST_4( miscMatrices(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST_5( miscMatrices(MatrixXcd(20, 20)) );
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_NO_STATIC_ASSERT
|
||||
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_DONT_VECTORIZE
|
||||
#define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
|
||||
template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
|
||||
{
|
||||
typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
|
||||
typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
|
||||
typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
|
||||
typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
|
||||
typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
|
||||
typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
|
||||
typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
|
||||
typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;
|
||||
|
||||
Mat_f mf(size,size);
|
||||
Mat_d md(size,size);
|
||||
Mat_cf mcf(size,size);
|
||||
Mat_cd mcd(size,size);
|
||||
Vec_f vf(size,1);
|
||||
Vec_d vd(size,1);
|
||||
Vec_cf vcf(size,1);
|
||||
Vec_cd vcd(size,1);
|
||||
|
||||
mf+mf;
|
||||
VERIFY_RAISES_ASSERT(mf+md);
|
||||
VERIFY_RAISES_ASSERT(mf+mcf);
|
||||
VERIFY_RAISES_ASSERT(vf=vd);
|
||||
VERIFY_RAISES_ASSERT(vf+=vd);
|
||||
VERIFY_RAISES_ASSERT(mcd=md);
|
||||
|
||||
mf*mf;
|
||||
md*mcd;
|
||||
mcd*md;
|
||||
mf*vcf;
|
||||
mcf*vf;
|
||||
mcf *= mf;
|
||||
vcd = md*vcd;
|
||||
vcf = mcf*vf;
|
||||
#if 0
|
||||
// these are know generating hard build errors in eigen3
|
||||
VERIFY_RAISES_ASSERT(mf*md);
|
||||
VERIFY_RAISES_ASSERT(mcf*mcd);
|
||||
VERIFY_RAISES_ASSERT(mcf*vcd);
|
||||
VERIFY_RAISES_ASSERT(vcf = mf*vf);
|
||||
|
||||
vf.eigen2_dot(vf);
|
||||
VERIFY_RAISES_ASSERT(vd.eigen2_dot(vf));
|
||||
VERIFY_RAISES_ASSERT(vcf.eigen2_dot(vf)); // yeah eventually we should allow this but i'm too lazy to make that change now in Dot.h
|
||||
// especially as that might be rewritten as cwise product .sum() which would make that automatic.
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_eigen2_mixingtypes()
|
||||
{
|
||||
// check that our operator new is indeed called:
|
||||
CALL_SUBTEST_1(mixingtypes<3>());
|
||||
CALL_SUBTEST_2(mixingtypes<4>());
|
||||
CALL_SUBTEST_3(mixingtypes<Dynamic>(20));
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN_USE_NEW_STDVECTOR
|
||||
#include "main.h"
|
||||
#include <Eigen/StdVector>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
template<typename MatrixType>
|
||||
void check_stdvector_matrix(const MatrixType& m)
|
||||
{
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
|
||||
std::vector<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.resize(22,y);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(MatrixType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
MatrixType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(unsigned int i=23; i<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i]==w[(i-23)%w.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TransformType>
|
||||
void check_stdvector_transform(const TransformType&)
|
||||
{
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
TransformType x(MatrixType::Random()), y(MatrixType::Random());
|
||||
std::vector<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.resize(22,y);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(TransformType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
TransformType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(unsigned int i=23; i<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename QuaternionType>
|
||||
void check_stdvector_quaternion(const QuaternionType&)
|
||||
{
|
||||
typedef typename QuaternionType::Coefficients Coefficients;
|
||||
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
|
||||
std::vector<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.resize(22,y);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(QuaternionType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
QuaternionType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(unsigned int i=23; i<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
|
||||
}
|
||||
}
|
||||
|
||||
void test_eigen2_newstdvector()
|
||||
{
|
||||
// some non vectorizable fixed sizes
|
||||
CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
|
||||
CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
|
||||
CALL_SUBTEST_1(check_stdvector_matrix(Matrix3d()));
|
||||
|
||||
// some vectorizable fixed sizes
|
||||
CALL_SUBTEST_2(check_stdvector_matrix(Matrix2f()));
|
||||
CALL_SUBTEST_2(check_stdvector_matrix(Vector4f()));
|
||||
CALL_SUBTEST_2(check_stdvector_matrix(Matrix4f()));
|
||||
CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
|
||||
|
||||
// some dynamic sizes
|
||||
CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
|
||||
CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
|
||||
CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
|
||||
CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
|
||||
|
||||
// some Transform
|
||||
CALL_SUBTEST_4(check_stdvector_transform(Transform2f()));
|
||||
CALL_SUBTEST_4(check_stdvector_transform(Transform3f()));
|
||||
CALL_SUBTEST_4(check_stdvector_transform(Transform3d()));
|
||||
//CALL_SUBTEST(check_stdvector_transform(Transform4d()));
|
||||
|
||||
// some Quaternion
|
||||
CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
|
||||
CALL_SUBTEST_5(check_stdvector_quaternion(Quaterniond()));
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// this hack is needed to make this file compiles with -pedantic (gcc)
|
||||
#ifdef __GNUC__
|
||||
#define throw(X)
|
||||
#endif
|
||||
// discard stack allocation as that too bypasses malloc
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 0
|
||||
// any heap allocation will raise an assert
|
||||
#define EIGEN_NO_MALLOC
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void nomalloc(const MatrixType& m)
|
||||
{
|
||||
/* this test check no dynamic memory allocation are issued with fixed-size matrices
|
||||
*/
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Identity(rows, rows),
|
||||
square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Random(rows, rows);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
Scalar s1 = ei_random<Scalar>();
|
||||
|
||||
int r = ei_random<int>(0, rows-1),
|
||||
c = ei_random<int>(0, cols-1);
|
||||
|
||||
VERIFY_IS_APPROX((m1+m2)*s1, s1*m1+s1*m2);
|
||||
VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
|
||||
VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
|
||||
VERIFY_IS_APPROX((m1*m1.transpose())*m2, m1*(m1.transpose()*m2));
|
||||
}
|
||||
|
||||
void test_eigen2_nomalloc()
|
||||
{
|
||||
// check that our operator new is indeed called:
|
||||
VERIFY_RAISES_ASSERT(MatrixXd dummy = MatrixXd::Random(3,3));
|
||||
CALL_SUBTEST_1( nomalloc(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( nomalloc(Matrix4d()) );
|
||||
CALL_SUBTEST_3( nomalloc(Matrix<float,32,32>()) );
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
// using namespace Eigen;
|
||||
|
||||
template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int size)
|
||||
{
|
||||
for (int i=0; i<size; ++i)
|
||||
if (!ei_isApprox(a[i],b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CHECK_CWISE(REFOP, POP) { \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
|
||||
ei_pstore(data2, POP(ei_pload(data1), ei_pload(data1+PacketSize))); \
|
||||
VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
#define REF_ADD(a,b) ((a)+(b))
|
||||
#define REF_SUB(a,b) ((a)-(b))
|
||||
#define REF_MUL(a,b) ((a)*(b))
|
||||
#define REF_DIV(a,b) ((a)/(b))
|
||||
|
||||
namespace std {
|
||||
|
||||
template<> const complex<float>& min(const complex<float>& a, const complex<float>& b)
|
||||
{ return a.real() < b.real() ? a : b; }
|
||||
|
||||
template<> const complex<float>& max(const complex<float>& a, const complex<float>& b)
|
||||
{ return a.real() < b.real() ? b : a; }
|
||||
|
||||
}
|
||||
|
||||
template<typename Scalar> void packetmath()
|
||||
{
|
||||
typedef typename ei_packet_traits<Scalar>::type Packet;
|
||||
const int PacketSize = ei_packet_traits<Scalar>::size;
|
||||
|
||||
const int size = PacketSize*4;
|
||||
EIGEN_ALIGN_128 Scalar data1[ei_packet_traits<Scalar>::size*4];
|
||||
EIGEN_ALIGN_128 Scalar data2[ei_packet_traits<Scalar>::size*4];
|
||||
EIGEN_ALIGN_128 Packet packets[PacketSize*2];
|
||||
EIGEN_ALIGN_128 Scalar ref[ei_packet_traits<Scalar>::size*4];
|
||||
for (int i=0; i<size; ++i)
|
||||
{
|
||||
data1[i] = ei_random<Scalar>();
|
||||
data2[i] = ei_random<Scalar>();
|
||||
}
|
||||
|
||||
ei_pstore(data2, ei_pload(data1));
|
||||
VERIFY(areApprox(data1, data2, PacketSize) && "aligned load/store");
|
||||
|
||||
for (int offset=0; offset<PacketSize; ++offset)
|
||||
{
|
||||
ei_pstore(data2, ei_ploadu(data1+offset));
|
||||
VERIFY(areApprox(data1+offset, data2, PacketSize) && "ei_ploadu");
|
||||
}
|
||||
|
||||
for (int offset=0; offset<PacketSize; ++offset)
|
||||
{
|
||||
ei_pstoreu(data2+offset, ei_pload(data1));
|
||||
VERIFY(areApprox(data1, data2+offset, PacketSize) && "ei_pstoreu");
|
||||
}
|
||||
|
||||
for (int offset=0; offset<PacketSize; ++offset)
|
||||
{
|
||||
packets[0] = ei_pload(data1);
|
||||
packets[1] = ei_pload(data1+PacketSize);
|
||||
if (offset==0) ei_palign<0>(packets[0], packets[1]);
|
||||
else if (offset==1) ei_palign<1>(packets[0], packets[1]);
|
||||
else if (offset==2) ei_palign<2>(packets[0], packets[1]);
|
||||
else if (offset==3) ei_palign<3>(packets[0], packets[1]);
|
||||
ei_pstore(data2, packets[0]);
|
||||
|
||||
for (int i=0; i<PacketSize; ++i)
|
||||
ref[i] = data1[i+offset];
|
||||
|
||||
typedef Matrix<Scalar, PacketSize, 1> Vector;
|
||||
VERIFY(areApprox(ref, data2, PacketSize) && "ei_palign");
|
||||
}
|
||||
|
||||
CHECK_CWISE(REF_ADD, ei_padd);
|
||||
CHECK_CWISE(REF_SUB, ei_psub);
|
||||
CHECK_CWISE(REF_MUL, ei_pmul);
|
||||
#ifndef EIGEN_VECTORIZE_ALTIVEC
|
||||
if (!ei_is_same_type<Scalar,int>::ret)
|
||||
CHECK_CWISE(REF_DIV, ei_pdiv);
|
||||
#endif
|
||||
CHECK_CWISE(std::min, ei_pmin);
|
||||
CHECK_CWISE(std::max, ei_pmax);
|
||||
|
||||
for (int i=0; i<PacketSize; ++i)
|
||||
ref[i] = data1[0];
|
||||
ei_pstore(data2, ei_pset1(data1[0]));
|
||||
VERIFY(areApprox(ref, data2, PacketSize) && "ei_pset1");
|
||||
|
||||
VERIFY(ei_isApprox(data1[0], ei_pfirst(ei_pload(data1))) && "ei_pfirst");
|
||||
|
||||
ref[0] = 0;
|
||||
for (int i=0; i<PacketSize; ++i)
|
||||
ref[0] += data1[i];
|
||||
VERIFY(ei_isApprox(ref[0], ei_predux(ei_pload(data1))) && "ei_predux");
|
||||
|
||||
for (int j=0; j<PacketSize; ++j)
|
||||
{
|
||||
ref[j] = 0;
|
||||
for (int i=0; i<PacketSize; ++i)
|
||||
ref[j] += data1[i+j*PacketSize];
|
||||
packets[j] = ei_pload(data1+j*PacketSize);
|
||||
}
|
||||
ei_pstore(data2, ei_preduxp(packets));
|
||||
VERIFY(areApprox(ref, data2, PacketSize) && "ei_preduxp");
|
||||
}
|
||||
|
||||
void test_eigen2_packetmath()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( packetmath<float>() );
|
||||
CALL_SUBTEST_2( packetmath<double>() );
|
||||
CALL_SUBTEST_3( packetmath<int>() );
|
||||
CALL_SUBTEST_4( packetmath<std::complex<float> >() );
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename LineType> void parametrizedline(const LineType& _line)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
ParametrizedLine.h
|
||||
*/
|
||||
|
||||
const int dim = _line.dim();
|
||||
typedef typename LineType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime,
|
||||
LineType::AmbientDimAtCompileTime> MatrixType;
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
|
||||
VectorType d0 = VectorType::Random(dim).normalized();
|
||||
|
||||
LineType l0(p0, d0);
|
||||
|
||||
Scalar s0 = ei_random<Scalar>();
|
||||
Scalar s1 = ei_abs(ei_random<Scalar>());
|
||||
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0), RealScalar(1) );
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) );
|
||||
VERIFY_IS_APPROX( (l0.projection(p1)-p1).norm(), l0.distance(p1) );
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(l0.projection(p1)), RealScalar(1) );
|
||||
VERIFY_IS_APPROX( Scalar(l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1)), s1 );
|
||||
|
||||
// casting
|
||||
const int Dim = LineType::AmbientDimAtCompileTime;
|
||||
typedef typename GetDifferentType<Scalar>::type OtherScalar;
|
||||
ParametrizedLine<OtherScalar,Dim> hp1f = l0.template cast<OtherScalar>();
|
||||
VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),l0);
|
||||
ParametrizedLine<Scalar,Dim> hp1d = l0.template cast<Scalar>();
|
||||
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),l0);
|
||||
}
|
||||
|
||||
void test_eigen2_parametrizedline()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
|
||||
CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
|
||||
CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
|
||||
CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
#include <algorithm>
|
||||
|
||||
template<typename T> std::string type_name() { return "other"; }
|
||||
template<> std::string type_name<float>() { return "float"; }
|
||||
template<> std::string type_name<double>() { return "double"; }
|
||||
template<> std::string type_name<int>() { return "int"; }
|
||||
template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
|
||||
template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
|
||||
template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
|
||||
|
||||
#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
|
||||
|
||||
template<typename T> inline typename NumTraits<T>::Real epsilon()
|
||||
{
|
||||
return std::numeric_limits<typename NumTraits<T>::Real>::epsilon();
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_permutation_4x4()
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
Vector4i indices(0,1,2,3);
|
||||
for(int i = 0; i < 24; ++i)
|
||||
{
|
||||
MatrixType m = MatrixType::Zero();
|
||||
m(indices(0),0) = 1;
|
||||
m(indices(1),1) = 1;
|
||||
m(indices(2),2) = 1;
|
||||
m(indices(3),3) = 1;
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() );
|
||||
VERIFY(error == 0.0);
|
||||
std::next_permutation(indices.data(),indices.data()+4);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_general_4x4(int repeat)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
double error_sum = 0., error_max = 0.;
|
||||
for(int i = 0; i < repeat; ++i)
|
||||
{
|
||||
MatrixType m;
|
||||
RealScalar absdet;
|
||||
do {
|
||||
m = MatrixType::Random();
|
||||
absdet = ei_abs(m.determinant());
|
||||
} while(absdet < 10 * epsilon<Scalar>());
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / epsilon<Scalar>() );
|
||||
error_sum += error;
|
||||
error_max = std::max(error_max, error);
|
||||
}
|
||||
std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl;
|
||||
double error_avg = error_sum / repeat;
|
||||
EIGEN_DEBUG_VAR(error_avg);
|
||||
EIGEN_DEBUG_VAR(error_max);
|
||||
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
|
||||
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
|
||||
}
|
||||
|
||||
void test_eigen2_prec_inverse_4x4()
|
||||
{
|
||||
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
|
||||
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
||||
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
|
||||
CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "product.h"
|
||||
|
||||
void test_eigen2_product_large()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( product(MatrixXf(ei_random<int>(1,320), ei_random<int>(1,320))) );
|
||||
CALL_SUBTEST_2( product(MatrixXd(ei_random<int>(1,320), ei_random<int>(1,320))) );
|
||||
CALL_SUBTEST_3( product(MatrixXi(ei_random<int>(1,320), ei_random<int>(1,320))) );
|
||||
CALL_SUBTEST_4( product(MatrixXcf(ei_random<int>(1,50), ei_random<int>(1,50))) );
|
||||
CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(ei_random<int>(1,320), ei_random<int>(1,320))) );
|
||||
}
|
||||
|
||||
#ifdef EIGEN_TEST_PART_6
|
||||
{
|
||||
// test a specific issue in DiagonalProduct
|
||||
int N = 1000000;
|
||||
VectorXf v = VectorXf::Ones(N);
|
||||
MatrixXf m = MatrixXf::Ones(N,3);
|
||||
m = (v+v).asDiagonal() * m;
|
||||
VERIFY_IS_APPROX(m, MatrixXf::Constant(N,3,2));
|
||||
}
|
||||
|
||||
{
|
||||
// test deferred resizing in Matrix::operator=
|
||||
MatrixXf a = MatrixXf::Random(10,4), b = MatrixXf::Random(4,10), c = a;
|
||||
VERIFY_IS_APPROX((a = a * b), (c * b).eval());
|
||||
}
|
||||
|
||||
{
|
||||
MatrixXf mat1(10,10); mat1.setRandom();
|
||||
MatrixXf mat2(32,10); mat2.setRandom();
|
||||
MatrixXf result = mat1.row(2)*mat2.transpose();
|
||||
VERIFY_IS_APPROX(result, (mat1.row(2)*mat2.transpose()).eval());
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN_NO_STATIC_ASSERT
|
||||
#include "product.h"
|
||||
|
||||
void test_eigen2_product_small()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
|
||||
CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
|
||||
CALL_SUBTEST_3( product(Matrix3d()) );
|
||||
CALL_SUBTEST_4( product(Matrix4d()) );
|
||||
CALL_SUBTEST_5( product(Matrix4f()) );
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename MatrixType> void qr(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
QR.h
|
||||
*/
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> SquareMatrixType;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
QR<MatrixType> qrOfA(a);
|
||||
VERIFY_IS_APPROX(a, qrOfA.matrixQ() * qrOfA.matrixR());
|
||||
VERIFY_IS_NOT_APPROX(a+MatrixType::Identity(rows, cols), qrOfA.matrixQ() * qrOfA.matrixR());
|
||||
|
||||
#if 0 // eigenvalues module not yet ready
|
||||
SquareMatrixType b = a.adjoint() * a;
|
||||
|
||||
// check tridiagonalization
|
||||
Tridiagonalization<SquareMatrixType> tridiag(b);
|
||||
VERIFY_IS_APPROX(b, tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint());
|
||||
|
||||
// check hessenberg decomposition
|
||||
HessenbergDecomposition<SquareMatrixType> hess(b);
|
||||
VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
|
||||
VERIFY_IS_APPROX(tridiag.matrixT(), hess.matrixH());
|
||||
b = SquareMatrixType::Random(cols,cols);
|
||||
hess.compute(b);
|
||||
VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_eigen2_qr()
|
||||
{
|
||||
for(int i = 0; i < 1; i++) {
|
||||
CALL_SUBTEST_1( qr(Matrix2f()) );
|
||||
CALL_SUBTEST_2( qr(Matrix4d()) );
|
||||
CALL_SUBTEST_3( qr(MatrixXf(12,8)) );
|
||||
CALL_SUBTEST_4( qr(MatrixXcd(5,5)) );
|
||||
CALL_SUBTEST_4( qr(MatrixXcd(7,3)) );
|
||||
}
|
||||
|
||||
#ifdef EIGEN_TEST_PART_5
|
||||
// small isFullRank test
|
||||
{
|
||||
Matrix3d mat;
|
||||
mat << 1, 45, 1, 2, 2, 2, 1, 2, 3;
|
||||
VERIFY(mat.qr().isFullRank());
|
||||
mat << 1, 1, 1, 2, 2, 2, 1, 2, 3;
|
||||
//always returns true in eigen2support
|
||||
//VERIFY(!mat.qr().isFullRank());
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/QtAlignedMalloc>
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
template<typename MatrixType>
|
||||
void check_qtvector_matrix(const MatrixType& m)
|
||||
{
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
|
||||
QVector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], y);
|
||||
}
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.fill(y,22);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
MatrixType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(int i=23; i<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i]==w[(i-23)%w.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TransformType>
|
||||
void check_qtvector_transform(const TransformType&)
|
||||
{
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
TransformType x(MatrixType::Random()), y(MatrixType::Random());
|
||||
QVector<TransformType> v(10), w(20, y);
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.fill(y,22);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
TransformType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(unsigned int i=23; int(i)<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename QuaternionType>
|
||||
void check_qtvector_quaternion(const QuaternionType&)
|
||||
{
|
||||
typedef typename QuaternionType::Coefficients Coefficients;
|
||||
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
|
||||
QVector<QuaternionType> v(10), w(20, y);
|
||||
v[5] = x;
|
||||
w[6] = v[5];
|
||||
VERIFY_IS_APPROX(w[6], v[5]);
|
||||
v = w;
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
VERIFY_IS_APPROX(w[i], v[i]);
|
||||
}
|
||||
|
||||
v.resize(21);
|
||||
v[20] = x;
|
||||
VERIFY_IS_APPROX(v[20], x);
|
||||
v.fill(y,22);
|
||||
VERIFY_IS_APPROX(v[21], y);
|
||||
v.push_back(x);
|
||||
VERIFY_IS_APPROX(v[22], x);
|
||||
VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
|
||||
|
||||
// do a lot of push_back such that the vector gets internally resized
|
||||
// (with memory reallocation)
|
||||
QuaternionType* ref = &w[0];
|
||||
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
|
||||
v.push_back(w[i%w.size()]);
|
||||
for(unsigned int i=23; int(i)<v.size(); ++i)
|
||||
{
|
||||
VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
|
||||
}
|
||||
}
|
||||
|
||||
void test_eigen2_qtvector()
|
||||
{
|
||||
// some non vectorizable fixed sizes
|
||||
CALL_SUBTEST_1(check_qtvector_matrix(Vector2f()));
|
||||
CALL_SUBTEST_1(check_qtvector_matrix(Matrix3f()));
|
||||
CALL_SUBTEST_1(check_qtvector_matrix(Matrix3d()));
|
||||
|
||||
// some vectorizable fixed sizes
|
||||
CALL_SUBTEST_2(check_qtvector_matrix(Matrix2f()));
|
||||
CALL_SUBTEST_2(check_qtvector_matrix(Vector4f()));
|
||||
CALL_SUBTEST_2(check_qtvector_matrix(Matrix4f()));
|
||||
CALL_SUBTEST_2(check_qtvector_matrix(Matrix4d()));
|
||||
|
||||
// some dynamic sizes
|
||||
CALL_SUBTEST_3(check_qtvector_matrix(MatrixXd(1,1)));
|
||||
CALL_SUBTEST_3(check_qtvector_matrix(VectorXd(20)));
|
||||
CALL_SUBTEST_3(check_qtvector_matrix(RowVectorXf(20)));
|
||||
CALL_SUBTEST_3(check_qtvector_matrix(MatrixXcf(10,10)));
|
||||
|
||||
// some Transform
|
||||
CALL_SUBTEST_4(check_qtvector_transform(Transform2f()));
|
||||
CALL_SUBTEST_4(check_qtvector_transform(Transform3f()));
|
||||
CALL_SUBTEST_4(check_qtvector_transform(Transform3d()));
|
||||
//CALL_SUBTEST_4(check_qtvector_transform(Transform4d()));
|
||||
|
||||
// some Quaternion
|
||||
CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
|
||||
CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LeastSquares>
|
||||
|
||||
template<typename VectorType,
|
||||
typename HyperplaneType>
|
||||
void makeNoisyCohyperplanarPoints(int numPoints,
|
||||
VectorType **points,
|
||||
HyperplaneType *hyperplane,
|
||||
typename VectorType::Scalar noiseAmplitude)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
const int size = points[0]->size();
|
||||
// pick a random hyperplane, store the coefficients of its equation
|
||||
hyperplane->coeffs().resize(size + 1);
|
||||
for(int j = 0; j < size + 1; j++)
|
||||
{
|
||||
do {
|
||||
hyperplane->coeffs().coeffRef(j) = ei_random<Scalar>();
|
||||
} while(ei_abs(hyperplane->coeffs().coeff(j)) < 0.5);
|
||||
}
|
||||
|
||||
// now pick numPoints random points on this hyperplane
|
||||
for(int i = 0; i < numPoints; i++)
|
||||
{
|
||||
VectorType& cur_point = *(points[i]);
|
||||
do
|
||||
{
|
||||
cur_point = VectorType::Random(size)/*.normalized()*/;
|
||||
// project cur_point onto the hyperplane
|
||||
Scalar x = - (hyperplane->coeffs().start(size).cwise()*cur_point).sum();
|
||||
cur_point *= hyperplane->coeffs().coeff(size) / x;
|
||||
} while( cur_point.norm() < 0.5
|
||||
|| cur_point.norm() > 2.0 );
|
||||
}
|
||||
|
||||
// add some noise to these points
|
||||
for(int i = 0; i < numPoints; i++ )
|
||||
*(points[i]) += noiseAmplitude * VectorType::Random(size);
|
||||
}
|
||||
|
||||
template<typename VectorType>
|
||||
void check_linearRegression(int numPoints,
|
||||
VectorType **points,
|
||||
const VectorType& original,
|
||||
typename VectorType::Scalar tolerance)
|
||||
{
|
||||
int size = points[0]->size();
|
||||
assert(size==2);
|
||||
VectorType result(size);
|
||||
linearRegression(numPoints, points, &result, 1);
|
||||
typename VectorType::Scalar error = (result - original).norm() / original.norm();
|
||||
VERIFY(ei_abs(error) < ei_abs(tolerance));
|
||||
}
|
||||
|
||||
template<typename VectorType,
|
||||
typename HyperplaneType>
|
||||
void check_fitHyperplane(int numPoints,
|
||||
VectorType **points,
|
||||
const HyperplaneType& original,
|
||||
typename VectorType::Scalar tolerance)
|
||||
{
|
||||
int size = points[0]->size();
|
||||
HyperplaneType result(size);
|
||||
fitHyperplane(numPoints, points, &result);
|
||||
result.coeffs() *= original.coeffs().coeff(size)/result.coeffs().coeff(size);
|
||||
typename VectorType::Scalar error = (result.coeffs() - original.coeffs()).norm() / original.coeffs().norm();
|
||||
std::cout << ei_abs(error) << " xxx " << ei_abs(tolerance) << std::endl;
|
||||
VERIFY(ei_abs(error) < ei_abs(tolerance));
|
||||
}
|
||||
|
||||
void test_eigen2_regression()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++)
|
||||
{
|
||||
#ifdef EIGEN_TEST_PART_1
|
||||
{
|
||||
Vector2f points2f [1000];
|
||||
Vector2f *points2f_ptrs [1000];
|
||||
for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
|
||||
Vector2f coeffs2f;
|
||||
Hyperplane<float,2> coeffs3f;
|
||||
makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
|
||||
coeffs2f[0] = -coeffs3f.coeffs()[0]/coeffs3f.coeffs()[1];
|
||||
coeffs2f[1] = -coeffs3f.coeffs()[2]/coeffs3f.coeffs()[1];
|
||||
CALL_SUBTEST(check_linearRegression(10, points2f_ptrs, coeffs2f, 0.05f));
|
||||
CALL_SUBTEST(check_linearRegression(100, points2f_ptrs, coeffs2f, 0.01f));
|
||||
CALL_SUBTEST(check_linearRegression(1000, points2f_ptrs, coeffs2f, 0.002f));
|
||||
}
|
||||
#endif
|
||||
#ifdef EIGEN_TEST_PART_2
|
||||
{
|
||||
Vector2f points2f [1000];
|
||||
Vector2f *points2f_ptrs [1000];
|
||||
for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
|
||||
Hyperplane<float,2> coeffs3f;
|
||||
makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
|
||||
CALL_SUBTEST(check_fitHyperplane(10, points2f_ptrs, coeffs3f, 0.05f));
|
||||
CALL_SUBTEST(check_fitHyperplane(100, points2f_ptrs, coeffs3f, 0.01f));
|
||||
CALL_SUBTEST(check_fitHyperplane(1000, points2f_ptrs, coeffs3f, 0.002f));
|
||||
}
|
||||
#endif
|
||||
#ifdef EIGEN_TEST_PART_3
|
||||
{
|
||||
Vector4d points4d [1000];
|
||||
Vector4d *points4d_ptrs [1000];
|
||||
for(int i = 0; i < 1000; i++) points4d_ptrs[i] = &(points4d[i]);
|
||||
Hyperplane<double,4> coeffs5d;
|
||||
makeNoisyCohyperplanarPoints(1000, points4d_ptrs, &coeffs5d, 0.01);
|
||||
CALL_SUBTEST(check_fitHyperplane(10, points4d_ptrs, coeffs5d, 0.05));
|
||||
CALL_SUBTEST(check_fitHyperplane(100, points4d_ptrs, coeffs5d, 0.01));
|
||||
CALL_SUBTEST(check_fitHyperplane(1000, points4d_ptrs, coeffs5d, 0.002));
|
||||
}
|
||||
#endif
|
||||
#ifdef EIGEN_TEST_PART_4
|
||||
{
|
||||
VectorXcd *points11cd_ptrs[1000];
|
||||
for(int i = 0; i < 1000; i++) points11cd_ptrs[i] = new VectorXcd(11);
|
||||
Hyperplane<std::complex<double>,Dynamic> *coeffs12cd = new Hyperplane<std::complex<double>,Dynamic>(11);
|
||||
makeNoisyCohyperplanarPoints(1000, points11cd_ptrs, coeffs12cd, 0.01);
|
||||
CALL_SUBTEST(check_fitHyperplane(100, points11cd_ptrs, *coeffs12cd, 0.025));
|
||||
CALL_SUBTEST(check_fitHyperplane(1000, points11cd_ptrs, *coeffs12cd, 0.006));
|
||||
delete coeffs12cd;
|
||||
for(int i = 0; i < 1000; i++) delete points11cd_ptrs[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void verifySizeOf(const MatrixType&)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
|
||||
VERIFY(sizeof(MatrixType)==sizeof(Scalar)*MatrixType::SizeAtCompileTime);
|
||||
else
|
||||
VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
|
||||
}
|
||||
|
||||
void test_eigen2_sizeof()
|
||||
{
|
||||
CALL_SUBTEST( verifySizeOf(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST( verifySizeOf(Matrix4d()) );
|
||||
CALL_SUBTEST( verifySizeOf(Matrix<double, 4, 2>()) );
|
||||
CALL_SUBTEST( verifySizeOf(Matrix<bool, 7, 5>()) );
|
||||
CALL_SUBTEST( verifySizeOf(MatrixXcf(3, 3)) );
|
||||
CALL_SUBTEST( verifySizeOf(MatrixXi(8, 12)) );
|
||||
CALL_SUBTEST( verifySizeOf(MatrixXcd(20, 20)) );
|
||||
CALL_SUBTEST( verifySizeOf(Matrix<float, 100, 100>()) );
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename Scalar> void smallVectors()
|
||||
{
|
||||
typedef Matrix<Scalar, 1, 2> V2;
|
||||
typedef Matrix<Scalar, 3, 1> V3;
|
||||
typedef Matrix<Scalar, 1, 4> V4;
|
||||
Scalar x1 = ei_random<Scalar>(),
|
||||
x2 = ei_random<Scalar>(),
|
||||
x3 = ei_random<Scalar>(),
|
||||
x4 = ei_random<Scalar>();
|
||||
V2 v2(x1, x2);
|
||||
V3 v3(x1, x2, x3);
|
||||
V4 v4(x1, x2, x3, x4);
|
||||
VERIFY_IS_APPROX(x1, v2.x());
|
||||
VERIFY_IS_APPROX(x1, v3.x());
|
||||
VERIFY_IS_APPROX(x1, v4.x());
|
||||
VERIFY_IS_APPROX(x2, v2.y());
|
||||
VERIFY_IS_APPROX(x2, v3.y());
|
||||
VERIFY_IS_APPROX(x2, v4.y());
|
||||
VERIFY_IS_APPROX(x3, v3.z());
|
||||
VERIFY_IS_APPROX(x3, v4.z());
|
||||
VERIFY_IS_APPROX(x4, v4.w());
|
||||
}
|
||||
|
||||
void test_eigen2_smallvectors()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST( smallVectors<int>() );
|
||||
CALL_SUBTEST( smallVectors<float>() );
|
||||
CALL_SUBTEST( smallVectors<double>() );
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "sparse.h"
|
||||
|
||||
template<typename SetterType,typename DenseType, typename Scalar, int Options>
|
||||
bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
|
||||
{
|
||||
typedef SparseMatrix<Scalar,Options> SparseType;
|
||||
{
|
||||
sm.setZero();
|
||||
SetterType w(sm);
|
||||
std::vector<Vector2i> remaining = nonzeroCoords;
|
||||
while(!remaining.empty())
|
||||
{
|
||||
int i = ei_random<int>(0,remaining.size()-1);
|
||||
w(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
|
||||
remaining[i] = remaining.back();
|
||||
remaining.pop_back();
|
||||
}
|
||||
}
|
||||
return sm.isApprox(ref);
|
||||
}
|
||||
|
||||
template<typename SetterType,typename DenseType, typename T>
|
||||
bool test_random_setter(DynamicSparseMatrix<T>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
|
||||
{
|
||||
sm.setZero();
|
||||
std::vector<Vector2i> remaining = nonzeroCoords;
|
||||
while(!remaining.empty())
|
||||
{
|
||||
int i = ei_random<int>(0,remaining.size()-1);
|
||||
sm.coeffRef(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
|
||||
remaining[i] = remaining.back();
|
||||
remaining.pop_back();
|
||||
}
|
||||
return sm.isApprox(ref);
|
||||
}
|
||||
|
||||
template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
|
||||
{
|
||||
const int rows = ref.rows();
|
||||
const int cols = ref.cols();
|
||||
typedef typename SparseMatrixType::Scalar Scalar;
|
||||
enum { Flags = SparseMatrixType::Flags };
|
||||
|
||||
double density = std::max(8./(rows*cols), 0.01);
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
|
||||
typedef Matrix<Scalar,Dynamic,1> DenseVector;
|
||||
Scalar eps = 1e-6;
|
||||
|
||||
SparseMatrixType m(rows, cols);
|
||||
DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
|
||||
DenseVector vec1 = DenseVector::Random(rows);
|
||||
Scalar s1 = ei_random<Scalar>();
|
||||
|
||||
std::vector<Vector2i> zeroCoords;
|
||||
std::vector<Vector2i> nonzeroCoords;
|
||||
initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
|
||||
|
||||
if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
|
||||
return;
|
||||
|
||||
// test coeff and coeffRef
|
||||
for (int i=0; i<(int)zeroCoords.size(); ++i)
|
||||
{
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
|
||||
if(ei_is_same_type<SparseMatrixType,SparseMatrix<Scalar,Flags> >::ret)
|
||||
VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
|
||||
}
|
||||
VERIFY_IS_APPROX(m, refMat);
|
||||
|
||||
m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
|
||||
refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
|
||||
|
||||
VERIFY_IS_APPROX(m, refMat);
|
||||
/*
|
||||
// test InnerIterators and Block expressions
|
||||
for (int t=0; t<10; ++t)
|
||||
{
|
||||
int j = ei_random<int>(0,cols-1);
|
||||
int i = ei_random<int>(0,rows-1);
|
||||
int w = ei_random<int>(1,cols-j-1);
|
||||
int h = ei_random<int>(1,rows-i-1);
|
||||
|
||||
// VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
|
||||
for(int c=0; c<w; c++)
|
||||
{
|
||||
VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
|
||||
for(int r=0; r<h; r++)
|
||||
{
|
||||
// VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
|
||||
}
|
||||
}
|
||||
// for(int r=0; r<h; r++)
|
||||
// {
|
||||
// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
|
||||
// for(int c=0; c<w; c++)
|
||||
// {
|
||||
// VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
for(int c=0; c<cols; c++)
|
||||
{
|
||||
VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
|
||||
VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
|
||||
}
|
||||
|
||||
for(int r=0; r<rows; r++)
|
||||
{
|
||||
VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
|
||||
VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
|
||||
}
|
||||
*/
|
||||
|
||||
// test SparseSetters
|
||||
// coherent setter
|
||||
// TODO extend the MatrixSetter
|
||||
// {
|
||||
// m.setZero();
|
||||
// VERIFY_IS_NOT_APPROX(m, refMat);
|
||||
// SparseSetter<SparseMatrixType, FullyCoherentAccessPattern> w(m);
|
||||
// for (int i=0; i<nonzeroCoords.size(); ++i)
|
||||
// {
|
||||
// w->coeffRef(nonzeroCoords[i].x(),nonzeroCoords[i].y()) = refMat.coeff(nonzeroCoords[i].x(),nonzeroCoords[i].y());
|
||||
// }
|
||||
// }
|
||||
// VERIFY_IS_APPROX(m, refMat);
|
||||
|
||||
// random setter
|
||||
// {
|
||||
// m.setZero();
|
||||
// VERIFY_IS_NOT_APPROX(m, refMat);
|
||||
// SparseSetter<SparseMatrixType, RandomAccessPattern> w(m);
|
||||
// std::vector<Vector2i> remaining = nonzeroCoords;
|
||||
// while(!remaining.empty())
|
||||
// {
|
||||
// int i = ei_random<int>(0,remaining.size()-1);
|
||||
// w->coeffRef(remaining[i].x(),remaining[i].y()) = refMat.coeff(remaining[i].x(),remaining[i].y());
|
||||
// remaining[i] = remaining.back();
|
||||
// remaining.pop_back();
|
||||
// }
|
||||
// }
|
||||
// VERIFY_IS_APPROX(m, refMat);
|
||||
|
||||
VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdMapTraits> >(m,refMat,nonzeroCoords) ));
|
||||
#ifdef EIGEN_UNORDERED_MAP_SUPPORT
|
||||
VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdUnorderedMapTraits> >(m,refMat,nonzeroCoords) ));
|
||||
#endif
|
||||
#ifdef _DENSE_HASH_MAP_H_
|
||||
VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleDenseHashMapTraits> >(m,refMat,nonzeroCoords) ));
|
||||
#endif
|
||||
#ifdef _SPARSE_HASH_MAP_H_
|
||||
VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleSparseHashMapTraits> >(m,refMat,nonzeroCoords) ));
|
||||
#endif
|
||||
|
||||
// test fillrand
|
||||
{
|
||||
DenseMatrix m1(rows,cols);
|
||||
m1.setZero();
|
||||
SparseMatrixType m2(rows,cols);
|
||||
m2.startFill();
|
||||
for (int j=0; j<cols; ++j)
|
||||
{
|
||||
for (int k=0; k<rows/2; ++k)
|
||||
{
|
||||
int i = ei_random<int>(0,rows-1);
|
||||
if (m1.coeff(i,j)==Scalar(0))
|
||||
m2.fillrand(i,j) = m1(i,j) = ei_random<Scalar>();
|
||||
}
|
||||
}
|
||||
m2.endFill();
|
||||
VERIFY_IS_APPROX(m2,m1);
|
||||
}
|
||||
|
||||
// test RandomSetter
|
||||
/*{
|
||||
SparseMatrixType m1(rows,cols), m2(rows,cols);
|
||||
DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
|
||||
initSparse<Scalar>(density, refM1, m1);
|
||||
{
|
||||
Eigen::RandomSetter<SparseMatrixType > setter(m2);
|
||||
for (int j=0; j<m1.outerSize(); ++j)
|
||||
for (typename SparseMatrixType::InnerIterator i(m1,j); i; ++i)
|
||||
setter(i.index(), j) = i.value();
|
||||
}
|
||||
VERIFY_IS_APPROX(m1, m2);
|
||||
}*/
|
||||
// std::cerr << m.transpose() << "\n\n" << refMat.transpose() << "\n\n";
|
||||
// VERIFY_IS_APPROX(m, refMat);
|
||||
|
||||
// test basic computations
|
||||
{
|
||||
DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType m1(rows, rows);
|
||||
SparseMatrixType m2(rows, rows);
|
||||
SparseMatrixType m3(rows, rows);
|
||||
SparseMatrixType m4(rows, rows);
|
||||
initSparse<Scalar>(density, refM1, m1);
|
||||
initSparse<Scalar>(density, refM2, m2);
|
||||
initSparse<Scalar>(density, refM3, m3);
|
||||
initSparse<Scalar>(density, refM4, m4);
|
||||
|
||||
VERIFY_IS_APPROX(m1+m2, refM1+refM2);
|
||||
VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
|
||||
VERIFY_IS_APPROX(m3.cwise()*(m1+m2), refM3.cwise()*(refM1+refM2));
|
||||
VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
|
||||
|
||||
VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
|
||||
VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
|
||||
|
||||
VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
|
||||
VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
|
||||
|
||||
VERIFY_IS_APPROX(m1.col(0).eigen2_dot(refM2.row(0)), refM1.col(0).eigen2_dot(refM2.row(0)));
|
||||
|
||||
refM4.setRandom();
|
||||
// sparse cwise* dense
|
||||
VERIFY_IS_APPROX(m3.cwise()*refM4, refM3.cwise()*refM4);
|
||||
// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
|
||||
}
|
||||
|
||||
// test innerVector()
|
||||
{
|
||||
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType m2(rows, rows);
|
||||
initSparse<Scalar>(density, refMat2, m2);
|
||||
int j0 = ei_random(0,rows-1);
|
||||
int j1 = ei_random(0,rows-1);
|
||||
VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
|
||||
VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
|
||||
//m2.innerVector(j0) = 2*m2.innerVector(j1);
|
||||
//refMat2.col(j0) = 2*refMat2.col(j1);
|
||||
//VERIFY_IS_APPROX(m2, refMat2);
|
||||
}
|
||||
|
||||
// test innerVectors()
|
||||
{
|
||||
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType m2(rows, rows);
|
||||
initSparse<Scalar>(density, refMat2, m2);
|
||||
int j0 = ei_random(0,rows-2);
|
||||
int j1 = ei_random(0,rows-2);
|
||||
int n0 = ei_random<int>(1,rows-std::max(j0,j1));
|
||||
VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
|
||||
VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
|
||||
refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
|
||||
//m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
|
||||
//refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
|
||||
}
|
||||
|
||||
// test transpose
|
||||
{
|
||||
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType m2(rows, rows);
|
||||
initSparse<Scalar>(density, refMat2, m2);
|
||||
VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
|
||||
VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
|
||||
}
|
||||
|
||||
// test prune
|
||||
{
|
||||
SparseMatrixType m2(rows, rows);
|
||||
DenseMatrix refM2(rows, rows);
|
||||
refM2.setZero();
|
||||
int countFalseNonZero = 0;
|
||||
int countTrueNonZero = 0;
|
||||
m2.startFill();
|
||||
for (int j=0; j<m2.outerSize(); ++j)
|
||||
for (int i=0; i<m2.innerSize(); ++i)
|
||||
{
|
||||
float x = ei_random<float>(0,1);
|
||||
if (x<0.1)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if (x<0.5)
|
||||
{
|
||||
countFalseNonZero++;
|
||||
m2.fill(i,j) = Scalar(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
countTrueNonZero++;
|
||||
m2.fill(i,j) = refM2(i,j) = Scalar(1);
|
||||
}
|
||||
}
|
||||
m2.endFill();
|
||||
VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
|
||||
VERIFY_IS_APPROX(m2, refM2);
|
||||
m2.prune(1);
|
||||
VERIFY(countTrueNonZero==m2.nonZeros());
|
||||
VERIFY_IS_APPROX(m2, refM2);
|
||||
}
|
||||
}
|
||||
|
||||
void test_eigen2_sparse_basic()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(8, 8)) );
|
||||
CALL_SUBTEST_2( sparse_basic(SparseMatrix<std::complex<double> >(16, 16)) );
|
||||
CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(33, 33)) );
|
||||
|
||||
CALL_SUBTEST_3( sparse_basic(DynamicSparseMatrix<double>(8, 8)) );
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "sparse.h"
|
||||
|
||||
template<typename SparseMatrixType> void sparse_product(const SparseMatrixType& ref)
|
||||
{
|
||||
const int rows = ref.rows();
|
||||
const int cols = ref.cols();
|
||||
typedef typename SparseMatrixType::Scalar Scalar;
|
||||
enum { Flags = SparseMatrixType::Flags };
|
||||
|
||||
double density = std::max(8./(rows*cols), 0.01);
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
|
||||
typedef Matrix<Scalar,Dynamic,1> DenseVector;
|
||||
|
||||
// test matrix-matrix product
|
||||
{
|
||||
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refMat3 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refMat4 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType m2(rows, rows);
|
||||
SparseMatrixType m3(rows, rows);
|
||||
SparseMatrixType m4(rows, rows);
|
||||
initSparse<Scalar>(density, refMat2, m2);
|
||||
initSparse<Scalar>(density, refMat3, m3);
|
||||
initSparse<Scalar>(density, refMat4, m4);
|
||||
VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
|
||||
VERIFY_IS_APPROX(m4=m2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
|
||||
VERIFY_IS_APPROX(m4=m2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
|
||||
VERIFY_IS_APPROX(m4=m2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
|
||||
|
||||
// sparse * dense
|
||||
VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
|
||||
VERIFY_IS_APPROX(dm4=m2*refMat3.transpose(), refMat4=refMat2*refMat3.transpose());
|
||||
VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3, refMat4=refMat2.transpose()*refMat3);
|
||||
VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
|
||||
|
||||
// dense * sparse
|
||||
VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
|
||||
VERIFY_IS_APPROX(dm4=refMat2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
|
||||
VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
|
||||
VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
|
||||
|
||||
VERIFY_IS_APPROX(m3=m3*m3, refMat3=refMat3*refMat3);
|
||||
}
|
||||
|
||||
// test matrix - diagonal product
|
||||
if(false) // it compiles, but the precision is terrible. probably doesn't matter in this branch....
|
||||
{
|
||||
DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
|
||||
DiagonalMatrix<DenseVector> d1(DenseVector::Random(rows));
|
||||
SparseMatrixType m2(rows, rows);
|
||||
SparseMatrixType m3(rows, rows);
|
||||
initSparse<Scalar>(density, refM2, m2);
|
||||
initSparse<Scalar>(density, refM3, m3);
|
||||
VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
|
||||
VERIFY_IS_APPROX(m3=m2.transpose()*d1, refM3=refM2.transpose()*d1);
|
||||
VERIFY_IS_APPROX(m3=d1*m2, refM3=d1*refM2);
|
||||
VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1 * refM2.transpose());
|
||||
}
|
||||
|
||||
// test self adjoint products
|
||||
{
|
||||
DenseMatrix b = DenseMatrix::Random(rows, rows);
|
||||
DenseMatrix x = DenseMatrix::Random(rows, rows);
|
||||
DenseMatrix refX = DenseMatrix::Random(rows, rows);
|
||||
DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
|
||||
DenseMatrix refS = DenseMatrix::Zero(rows, rows);
|
||||
SparseMatrixType mUp(rows, rows);
|
||||
SparseMatrixType mLo(rows, rows);
|
||||
SparseMatrixType mS(rows, rows);
|
||||
do {
|
||||
initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
|
||||
} while (refUp.isZero());
|
||||
refLo = refUp.transpose().conjugate();
|
||||
mLo = mUp.transpose().conjugate();
|
||||
refS = refUp + refLo;
|
||||
refS.diagonal() *= 0.5;
|
||||
mS = mUp + mLo;
|
||||
for (int k=0; k<mS.outerSize(); ++k)
|
||||
for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
|
||||
if (it.index() == k)
|
||||
it.valueRef() *= 0.5;
|
||||
|
||||
VERIFY_IS_APPROX(refS.adjoint(), refS);
|
||||
VERIFY_IS_APPROX(mS.transpose().conjugate(), mS);
|
||||
VERIFY_IS_APPROX(mS, refS);
|
||||
VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
|
||||
VERIFY_IS_APPROX(x=mUp.template marked<UpperTriangular|SelfAdjoint>()*b, refX=refS*b);
|
||||
VERIFY_IS_APPROX(x=mLo.template marked<LowerTriangular|SelfAdjoint>()*b, refX=refS*b);
|
||||
VERIFY_IS_APPROX(x=mS.template marked<SelfAdjoint>()*b, refX=refS*b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_eigen2_sparse_product()
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(8, 8)) );
|
||||
CALL_SUBTEST_2( sparse_product(SparseMatrix<std::complex<double> >(16, 16)) );
|
||||
CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(33, 33)) );
|
||||
|
||||
CALL_SUBTEST_3( sparse_product(DynamicSparseMatrix<double>(8, 8)) );
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user