Compare commits

...

58 Commits

Author SHA1 Message Date
Benoit Jacob
24fd14dab6 * minor dox tweaks
* pretext to bump to beta6
2009-01-12 16:14:13 +00:00
Benoit Jacob
4d44ca226e * make std::vector specializations also for Transform and for Quaternion
* update test_stdvector
* Quaternion() does nothing (instead of bug)
* update test_geometry
* some renaming
2009-01-12 16:06:04 +00:00
Gael Guennebaud
b26e12abcf make ei_traist<Select> honors nested types 2009-01-12 15:55:56 +00:00
Gael Guennebaud
a7554023a4 bugfix in ei_unaligned_type copy ctor 2009-01-12 15:51:49 +00:00
Gael Guennebaud
9d97c06d9d fix a warning in test/alignedbox 2009-01-12 15:29:51 +00:00
Gael Guennebaud
1fc17c4792 remove stupid output in test/meta 2009-01-12 15:27:25 +00:00
Gael Guennebaud
6efaece8ce disable/enable msvc headers are allowed to be included multiple times 2009-01-12 14:46:11 +00:00
Benoit Jacob
294f5f16dd muuuch improved documentation for the unaligned array assert.
also split into several pages for better reusability (more generally useful than
just for this assert)
2009-01-12 14:41:12 +00:00
Gael Guennebaud
f86818b5a6 bug fix in ei_stack_free 2009-01-12 14:20:21 +00:00
Benoit Jacob
336ad58213 * move cwise *= and /= to Core (like * and /)
* tidy the StdVector module
* fix warnings (especially a | instead of ||) in stdvector test
2009-01-12 13:41:40 +00:00
Gael Guennebaud
af5034b3c0 add a clean configuration summary for the unit tests (useful to analyze the dashboards) 2009-01-12 13:40:02 +00:00
Gael Guennebaud
7f881e814f another warning fix 2009-01-12 13:01:31 +00:00
Gael Guennebaud
a4252584ed bugfix in ei_handmade_aligned_free for null pointers 2009-01-12 12:54:32 +00:00
Gael Guennebaud
b365f443a2 make the testsuite works on windows with nmake 2009-01-12 12:53:41 +00:00
Gael Guennebaud
484ed3bbe2 fix a warning in test/sparse.h 2009-01-12 12:52:36 +00:00
Gael Guennebaud
92959aa5f3 add the possiblity to disable Fortran (workaround cmake's bug 2009-01-12 12:51:40 +00:00
Gael Guennebaud
2db5888253 update testsuite script 2009-01-12 11:55:52 +00:00
Gael Guennebaud
f268e79709 simplify some ei_traits<> using inheritance
(less loc and slight compilation speed up)
2009-01-11 22:03:40 +00:00
Gael Guennebaud
9e8f437a6f extend stdvector test with more push_back... 2009-01-11 21:59:04 +00:00
Benoit Jacob
824b75f182 forgot to commit updated test 2009-01-11 21:04:23 +00:00
Benoit Jacob
a30b498ab4 add cwise operator *= and /=.
Keir says hi!!
2009-01-11 20:48:56 +00:00
James Richard Tyrer
28e15574df updating FindEigen2.cmake for proper search order 2009-01-11 16:18:59 +00:00
Armin Berres
6c84b03d77 add missing newline at EOF 2009-01-11 13:32:55 +00:00
Benoit Jacob
4361cb8913 EIGEN_NO_MALLOC must also block traditional unaligned malloc 2009-01-10 14:24:55 +00:00
Benoit Jacob
50ad8b9010 fix potential compilation issue on MSVC + no vectorization 2009-01-10 14:10:40 +00:00
Benoit Jacob
0c1ef2f4c6 make the std::vector fix work also with dynamic size Eigen objects, e.g.
std::vector<VectorXd>
update unit test
2009-01-10 13:10:23 +00:00
Benoit Jacob
3efe6e4176 remove ei_new_allocator
remove corresponding part of test_dynalloc
2009-01-10 02:50:09 +00:00
Benoit Jacob
335d3bcf05 Based on code + help from Alex Stapleton:
*Add Eigen/StdVector header.
Including it #includes<vector> and "Core" and generates a partial
specialization of std::vector<T> for T=Eigen::Matrix<...>
that will work even with vectorizable fixed-size Eigen types
(working around a design issue in the c++ STL)
*Add unit-test

CCMAIL: alex.stapleton@gmail.com
2009-01-09 23:26:45 +00:00
Benoit Jacob
5052d3659b oops, fix compilation (sorry for all that noise!) 2009-01-09 21:43:46 +00:00
Benoit Jacob
5bef59e371 (previous commit was bad) 2009-01-09 21:32:44 +00:00
Benoit Jacob
265ab86005 overloaded operator delete should call ei_conditinal_aligned_free, not
ei_aligned_free
2009-01-09 21:28:53 +00:00
Benoit Jacob
b3d580dec7 ei_aligned_delete was running through the various paths in the wrong
order
2009-01-09 20:57:06 +00:00
Benoit Jacob
fd831d5a12 * implement handmade aligned malloc, fast but always wastes 16 bytes of memory.
only used as fallback for now, needs benchmarking.
  also notice that some malloc() impls do waste memory to keep track of alignment
  and other stuff (check msdn's page on malloc).
* expand test_dynalloc to cover low level aligned alloc funcs. Remove the old
  #ifdef EIGEN_VECTORIZE...
* rewrite the logic choosing an aligned alloc, some new stuff:
  * malloc() already aligned on freebsd and windows x64 (plus apple already)
  * _mm_malloc() used only if EIGEN_VECTORIZE
  * posix_memalign: correct detection according to man page (not necessarily
    linux specific), don't attempt to declare it if the platform didn't declare it
    (there had to be a reason why it didn't declare it, right?)
2009-01-09 14:56:44 +00:00
Kenneth Frank Riddile
f52a9e5315 * Added aligned_allocator for using 16-byte aligned types with STL containers. There is still a compile-time problem with STL containers that have a standard-conformant resize() method, but this should resolve the original user issue which was storing aligned objects in a std::map. 2009-01-09 00:55:53 +00:00
Benoit Jacob
003d0ce03e add missing inline keywords (compilation error) spotted by timvdm 2009-01-08 20:20:11 +00:00
Gael Guennebaud
208b273106 change the day switch time to 5:00 UTC 2009-01-08 18:45:26 +00:00
Gael Guennebaud
b315f4c359 add a ctest testsuite.cmake script to simplify the generation of nightly builds 2009-01-08 18:38:58 +00:00
Benoit Jacob
51aa62a5d4 add EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
an ugly hack that allows people to do QVector<Vector4f> with Qt <= 4.4
the Qt bug this is working around is fixed by Gael in Qt 4.5
2009-01-08 16:03:24 +00:00
Benoit Jacob
eb7dcbbfce EIGEN_MAKE_ALIGNED_OPERATOR_NEW didn't actually need to get the class
name as parameter
2009-01-08 15:37:13 +00:00
Benoit Jacob
1d52bd4cad the big memory changes. the most important changes are:
ei_aligned_malloc now really behaves like a malloc
 (untyped, doesn't call ctor)
ei_aligned_new is the typed variant calling ctor
EIGEN_MAKE_ALIGNED_OPERATOR_NEW now takes the class name as parameter
2009-01-08 15:20:21 +00:00
Benoit Jacob
e2d2a7d222 fix a bug -- bad read found by valgrind 2009-01-08 14:23:30 +00:00
Gael Guennebaud
af27fb7590 Add cdash.org support:
* the dashboard is there: http://my.cdash.org/index.php?project=Eigen
* now you can run the tests from the top build dir
  and submit report like that (from the top build dir):
  ctest -D Experimental
* todo:
 - add some nighlty builds (I'll add a few on my computer)
 - add valgrind memory checks, performances tests, compilation time tests, etc.
2009-01-08 11:53:21 +00:00
Gael Guennebaud
8d3469ca44 add BLAS dependency in FindSuperLU.cmake 2009-01-08 11:27:02 +00:00
Gael Guennebaud
4432cf8ca3 bugfix in sum 2009-01-08 10:36:54 +00:00
Gael Guennebaud
cb71dc4bbf Add a vectorization_logic unit test for assign and sum.
Need to add dot and more tests, but it seems I've already
found some room for improvement in sum.
2009-01-07 22:20:03 +00:00
Gael Guennebaud
709e903335 Sparse module:
* extend unit tests
* add support for generic sum reduction and dot product
* optimize the cwise()* : this is a special case of CwiseBinaryOp where
  we only have to process the coeffs which are not null for *both* matrices.
  Perhaps there exist some other binary operations like that ?
2009-01-07 17:01:57 +00:00
Kenneth Frank Riddile
7078cfaeaa * re-enabled deprecation warning on msvc now that eigen isn't using functions microsoft deems deprecated 2009-01-07 16:59:43 +00:00
Gael Guennebaud
336f0a8486 fine tuning in dot() and sum(), and prepare for the sparse versions... 2009-01-07 16:58:17 +00:00
Gael Guennebaud
6b9d647fc2 add custom implementation of hypot 2009-01-07 16:53:09 +00:00
Kenneth Frank Riddile
3e90940189 * disabled deprecation warning under msvc that was being triggered due to microsoft deprecating portable functions in favor of non-portable ones ( ex: hypot() deprecated in favor of _hypot() ) 2009-01-07 16:50:35 +00:00
Gael Guennebaud
8cea5f6b31 remove non standard hypotf function call 2009-01-07 16:24:27 +00:00
Gael Guennebaud
94efa16187 more Scalar conversions fixes 2009-01-07 10:22:46 +00:00
Gael Guennebaud
ac9d805c2f two scalar conversion fixes 2009-01-07 09:47:16 +00:00
Benoit Jacob
2db434265b remove the Matrix_ prefix 2009-01-06 18:07:16 +00:00
Armin Berres
8e888a45d0 call methods from the eigen namespace with prepended Eigen:: in define 2009-01-06 11:20:36 +00:00
Kenneth Frank Riddile
6736e52d25 * suppressed some minor warnings 2009-01-06 04:38:00 +00:00
Benoit Jacob
1c29d70312 * introduce macros to replace inheritance for operator new overloading
(former solution still available and tested)
  This plays much better with classes that already have base classes --
  don't force the user to mess with multiple inheritance, which gave
  much trouble with MSVC.
* Expand the unaligned assert dox page
* Minor fixes in the lazy evaluation dox page
2009-01-06 03:16:50 +00:00
Benoit Jacob
e71de20f16 ...so the placement new is really trivial:) 2009-01-05 20:06:52 +00:00
78 changed files with 2069 additions and 599 deletions

View File

@@ -1,5 +1,5 @@
project(Eigen)
set(EIGEN_VERSION_NUMBER "2.0-beta5")
set(EIGEN_VERSION_NUMBER "2.0-beta6")
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
#but won't stop CMake.
@@ -81,6 +81,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(Eigen)
if(EIGEN_BUILD_TESTS)
include(CTest)
add_subdirectory(test)
endif(EIGEN_BUILD_TESTS)

13
CTestConfig.cmake Normal file
View File

@@ -0,0 +1,13 @@
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
## # The following are required to uses Dart and the Cdash dashboard
## ENABLE_TESTING()
## INCLUDE(Dart)
set(CTEST_PROJECT_NAME "Eigen")
set(CTEST_NIGHTLY_START_TIME "05:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "www.cdash.org")
set(CTEST_DROP_LOCATION "/CDashPublic/submit.php?project=Eigen")
set(CTEST_DROP_SITE_CDASH TRUE)

View File

@@ -1,4 +1,4 @@
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression LeastSquares)
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression LeastSquares StdVector)
if(EIGEN_BUILD_LIB)
set(Eigen_SRCS

View File

@@ -3,7 +3,9 @@
// first thing Eigen does: prevent MSVC from committing suicide
#include "src/Core/util/DisableMSVCWarnings.h"
#ifdef _MSC_VER
#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
#if (_MSC_VER >= 1500) // 2008 or later
// Remember that usage of defined() in a #define is undefined by the standard
#ifdef _M_IX86_FP
@@ -57,10 +59,7 @@
#include <iostream>
#include <cstring>
#include <string>
#if defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER) && defined(EIGEN_VECTORIZE)
#include <malloc.h> // for _aligned_malloc
#endif
#include <limits>
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(EIGEN_NO_EXCEPTIONS)
#define EIGEN_EXCEPTIONS

View File

@@ -79,6 +79,7 @@ namespace Eigen {
#include "src/Sparse/SparseMatrix.h"
#include "src/Sparse/SparseVector.h"
#include "src/Sparse/CoreIterators.h"
#include "src/Sparse/SparseRedux.h"
#include "src/Sparse/SparseProduct.h"
#include "src/Sparse/TriangularSolver.h"
#include "src/Sparse/SparseLLT.h"

15
Eigen/StdVector Normal file
View File

@@ -0,0 +1,15 @@
#ifndef EIGEN_STDVECTOR_MODULE_H
#define EIGEN_STDVECTOR_MODULE_H
#include "Core"
#include <vector>
namespace Eigen {
#include "src/StdVector/UnalignedType.h"
} // namespace Eigen
namespace std {
#include "src/StdVector/StdVector.h"
} // namespace std
#endif // EIGEN_STDVECTOR_MODULE_H

View File

@@ -45,15 +45,18 @@ template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMat
struct ei_traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
{
typedef typename ei_traits<ThenMatrixType>::Scalar Scalar;
typedef typename ConditionMatrixType::Nested ConditionMatrixNested;
typedef typename ThenMatrixType::Nested ThenMatrixNested;
typedef typename ElseMatrixType::Nested ElseMatrixNested;
enum {
RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime,
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits,
CoeffReadCost = ei_traits<ConditionMatrixType>::CoeffReadCost
+ EIGEN_ENUM_MAX(ei_traits<ThenMatrixType>::CoeffReadCost,
ei_traits<ElseMatrixType>::CoeffReadCost)
CoeffReadCost = ei_traits<typename ei_cleantype<ConditionMatrixNested>::type>::CoeffReadCost
+ EIGEN_ENUM_MAX(ei_traits<typename ei_cleantype<ThenMatrixNested>::type>::CoeffReadCost,
ei_traits<typename ei_cleantype<ElseMatrixNested>::type>::CoeffReadCost)
};
};

View File

@@ -95,9 +95,9 @@ static void ei_cache_friendly_product(
const bool needRhsCopy = (PacketSize>1) && ((rhsStride%PacketSize!=0) || (size_t(rhs)%16!=0));
Scalar* EIGEN_RESTRICT block = 0;
const int allocBlockSize = l2BlockRows*size;
block = ei_aligned_stack_alloc(Scalar, allocBlockSize);
block = ei_aligned_stack_new(Scalar, allocBlockSize);
Scalar* EIGEN_RESTRICT rhsCopy
= ei_aligned_stack_alloc(Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
= ei_aligned_stack_new(Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
// loops on each L2 cache friendly blocks of the result
for(int l2i=0; l2i<rows; l2i+=l2BlockRows)
@@ -338,8 +338,8 @@ static void ei_cache_friendly_product(
}
}
ei_aligned_stack_free(block, Scalar, allocBlockSize);
ei_aligned_stack_free(rhsCopy, Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
ei_aligned_stack_delete(Scalar, block, allocBlockSize);
ei_aligned_stack_delete(Scalar, rhsCopy, l2BlockSizeAligned*l2BlockSizeAligned);
}
#endif // EIGEN_EXTERN_INSTANTIATIONS

View File

@@ -128,6 +128,12 @@ template<typename ExpressionType> class Cwise
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;

View File

@@ -224,6 +224,34 @@ Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
}
/** Replaces this expression by its coefficient-wise product with \a other.
*
* Example: \include Cwise_times_equal.cpp
* Output: \verbinclude Cwise_times_equal.out
*
* \sa operator*(), operator/=()
*/
template<typename ExpressionType>
template<typename OtherDerived>
inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
{
return m_matrix.const_cast_derived() = *this * other;
}
/** Replaces this expression by its coefficient-wise quotient by \a other.
*
* Example: \include Cwise_slash_equal.cpp
* Output: \verbinclude Cwise_slash_equal.out
*
* \sa operator/(), operator*=()
*/
template<typename ExpressionType>
template<typename OtherDerived>
inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
{
return m_matrix.const_cast_derived() = *this / other;
}
/** \returns an expression of the coefficient-wise min of *this and \a other
*
* Example: \include Cwise_min.cpp

View File

@@ -41,14 +41,9 @@
* \sa class CwiseUnaryOp, class CwiseBinaryOp, MatrixBase::NullaryExpr()
*/
template<typename NullaryOp, typename MatrixType>
struct ei_traits<CwiseNullaryOp<NullaryOp, MatrixType> >
struct ei_traits<CwiseNullaryOp<NullaryOp, MatrixType> > : ei_traits<MatrixType>
{
typedef typename ei_traits<MatrixType>::Scalar Scalar;
enum {
RowsAtCompileTime = ei_traits<MatrixType>::RowsAtCompileTime,
ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime,
MaxRowsAtCompileTime = ei_traits<MatrixType>::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ei_traits<MatrixType>::MaxColsAtCompileTime,
Flags = (ei_traits<MatrixType>::Flags
& ( HereditaryBits
| (ei_functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)

View File

@@ -41,6 +41,7 @@
*/
template<typename UnaryOp, typename MatrixType>
struct ei_traits<CwiseUnaryOp<UnaryOp, MatrixType> >
: ei_traits<MatrixType>
{
typedef typename ei_result_of<
UnaryOp(typename MatrixType::Scalar)
@@ -48,16 +49,10 @@ struct ei_traits<CwiseUnaryOp<UnaryOp, MatrixType> >
typedef typename MatrixType::Nested MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
MatrixTypeCoeffReadCost = _MatrixTypeNested::CoeffReadCost,
MatrixTypeFlags = _MatrixTypeNested::Flags,
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
Flags = (MatrixTypeFlags & (
Flags = (_MatrixTypeNested::Flags & (
HereditaryBits | LinearAccessBit | AlignedBit
| (ei_functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0))),
CoeffReadCost = MatrixTypeCoeffReadCost + ei_functor_traits<UnaryOp>::Cost
CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
};
};

View File

@@ -143,12 +143,13 @@ struct ei_dot_vec_unroller<Derived1, Derived2, Index, Stop, true>
template<typename Derived1, typename Derived2,
int Vectorization = ei_dot_traits<Derived1, Derived2>::Vectorization,
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling
int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling,
int Storage = (ei_traits<Derived1>::Flags | ei_traits<Derived2>::Flags) & SparseBit
>
struct ei_dot_impl;
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling, IsDense>
{
typedef typename Derived1::Scalar Scalar;
static Scalar run(const Derived1& v1, const Derived2& v2)
@@ -163,12 +164,12 @@ struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling, IsDense>
: public ei_dot_novec_unroller<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
{};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling, IsDense>
{
typedef typename Derived1::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -221,7 +222,7 @@ struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
};
template<typename Derived1, typename Derived2>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling, IsDense>
{
typedef typename Derived1::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -258,20 +259,15 @@ template<typename OtherDerived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
{
typedef typename Derived::Nested Nested;
typedef typename OtherDerived::Nested OtherNested;
typedef typename ei_unref<Nested>::type _Nested;
typedef typename ei_unref<OtherNested>::type _OtherNested;
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_Nested)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_OtherNested)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(_Nested,_OtherNested)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
ei_assert(size() == other.size());
return ei_dot_impl<_Nested, _OtherNested>::run(derived(), other.derived());
return ei_dot_impl<Derived, OtherDerived>::run(derived(), other.derived());
}
/** \returns the squared norm of *this, i.e. the dot product of *this with itself.
@@ -287,7 +283,7 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
template<typename Derived>
EIGEN_DEPRECATED inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm2() const
{
return ei_real(dot(*this));
return ei_real((*this).cwise().abs2().sum());
}
/** \returns the squared norm of *this, i.e. the dot product of *this with itself.
@@ -299,7 +295,7 @@ EIGEN_DEPRECATED inline typename NumTraits<typename ei_traits<Derived>::Scalar>:
template<typename Derived>
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
{
return ei_real(dot(*this));
return ei_real((*this).cwise().abs2().sum());
}
/** \returns the \em l2 norm of *this, i.e. the square root of the dot product of *this with itself.

View File

@@ -40,18 +40,9 @@
* \sa MatrixBase::flagged()
*/
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
struct ei_traits<Flagged<ExpressionType, Added, Removed> >
struct ei_traits<Flagged<ExpressionType, Added, Removed> > : ei_traits<ExpressionType>
{
typedef typename ExpressionType::Scalar Scalar;
enum {
RowsAtCompileTime = ExpressionType::RowsAtCompileTime,
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
Flags = (ExpressionType::Flags | Added) & ~Removed,
CoeffReadCost = ExpressionType::CoeffReadCost
};
enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
};
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged

View File

@@ -34,6 +34,16 @@ template<typename T> inline T ei_random_amplitude()
else return static_cast<T>(10);
}
template<typename T> inline T ei_hypot(T x, T y)
{
T _x = ei_abs(x);
T _y = ei_abs(y);
T p = std::max(_x, _y);
T q = std::min(_x, _y);
T qp = q/p;
return p * ei_sqrt(T(1) + qp*qp);
}
/**************
*** int ***
**************/
@@ -138,7 +148,7 @@ inline double ei_exp(double x) { return std::exp(x); }
inline double ei_log(double x) { return std::log(x); }
inline double ei_sin(double x) { return std::sin(x); }
inline double ei_cos(double x) { return std::cos(x); }
inline double ei_pow(double x, double y) { return std::pow(x, y); }
inline double ei_pow(double x, double y) { return std::pow(x, y); }
template<> inline double ei_random(double a, double b)
{

View File

@@ -25,6 +25,7 @@
#ifndef EIGEN_MATRIX_H
#define EIGEN_MATRIX_H
/** \class Matrix
*
* \brief The matrix class, also used for vectors and row-vectors
@@ -40,8 +41,8 @@
* \param _Cols Number of columns, or \b Dynamic
*
* The remaining template parameters are optional -- in most cases you don't have to worry about them.
* \param _Options A combination of either \b Matrix_RowMajor or \b Matrix_ColMajor, and of either
* \b Matrix_AutoAlign or \b Matrix_DontAlign.
* \param _Options A combination of either \b RowMajor or \b ColMajor, and of either
* \b AutoAlign or \b DontAlign.
* The former controls storage order, and defaults to column-major. The latter controls alignment, which is required
* for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size.
* \param _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
@@ -133,33 +134,9 @@ class Matrix
ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime, Options> m_storage;
public:
enum { NeedsToAlign = (Options&Matrix_AutoAlign) == Matrix_AutoAlign
enum { NeedsToAlign = (Options&AutoAlign) == AutoAlign
&& SizeAtCompileTime!=Dynamic && ((sizeof(Scalar)*SizeAtCompileTime)%16)==0 };
typedef typename ei_meta_if<NeedsToAlign, ei_byte_forcing_aligned_malloc, char>::ret ByteAlignedAsNeeded;
void *operator new(size_t size) throw()
{
return ei_aligned_malloc<ByteAlignedAsNeeded>(size);
}
void *operator new(size_t, void *ptr) throw()
{
return static_cast<void*>(ptr);
}
void *operator new[](size_t size) throw()
{
return ei_aligned_malloc<ByteAlignedAsNeeded>(size);
}
void *operator new[](size_t, void *ptr) throw()
{
return static_cast<void*>(ptr);
}
void operator delete(void * ptr) { ei_aligned_free(static_cast<ByteAlignedAsNeeded *>(ptr), 0); }
void operator delete[](void * ptr) { ei_aligned_free(static_cast<ByteAlignedAsNeeded *>(ptr), 0); }
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
EIGEN_STRONG_INLINE int cols() const { return m_storage.cols(); }
@@ -360,6 +337,9 @@ class Matrix
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
}
Matrix(ei_constructor_without_unaligned_array_assert)
: m_storage(ei_constructor_without_unaligned_array_assert()) {}
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
*
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,

View File

@@ -26,25 +26,33 @@
#ifndef EIGEN_MATRIXSTORAGE_H
#define EIGEN_MATRIXSTORAGE_H
struct ei_constructor_without_unaligned_array_assert {};
/** \internal
* Static array automatically aligned if the total byte size is a multiple of 16 and the matrix options require auto alignment
*/
template <typename T, int Size, int MatrixOptions,
bool Align = (MatrixOptions&Matrix_AutoAlign) && (((Size*sizeof(T))&0xf)==0)
bool Align = (MatrixOptions&AutoAlign) && (((Size*sizeof(T))&0xf)==0)
> struct ei_matrix_array
{
EIGEN_ALIGN_128 T array[Size];
ei_matrix_array()
{
#ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
ei_assert((reinterpret_cast<size_t>(array) & 0xf) == 0
&& "this assertion is explained here: http://eigen.tuxfamily.org/api/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
#endif
}
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
};
template <typename T, int Size, int MatrixOptions> struct ei_matrix_array<T,Size,MatrixOptions,false>
{
T array[Size];
ei_matrix_array() {}
ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
};
/** \internal
@@ -66,6 +74,8 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class ei_matr
ei_matrix_array<T,Size,_Options> m_data;
public:
inline explicit ei_matrix_storage() {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
: m_data(ei_constructor_without_unaligned_array_assert()) {}
inline ei_matrix_storage(int,int,int) {}
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); }
inline static int rows(void) {return _Rows;}
@@ -83,6 +93,8 @@ template<typename T, int Size, int _Options> class ei_matrix_storage<T, Size, Dy
int m_cols;
public:
inline explicit ei_matrix_storage() : m_rows(0), m_cols(0) {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
: m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
inline ei_matrix_storage(int, int rows, int cols) : m_rows(rows), m_cols(cols) {}
inline ~ei_matrix_storage() {}
inline void swap(ei_matrix_storage& other)
@@ -105,6 +117,8 @@ template<typename T, int Size, int _Cols, int _Options> class ei_matrix_storage<
int m_rows;
public:
inline explicit ei_matrix_storage() : m_rows(0) {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
: m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0) {}
inline ei_matrix_storage(int, int rows, int) : m_rows(rows) {}
inline ~ei_matrix_storage() {}
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
@@ -125,6 +139,8 @@ template<typename T, int Size, int _Rows, int _Options> class ei_matrix_storage<
int m_cols;
public:
inline explicit ei_matrix_storage() : m_cols(0) {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
: m_data(ei_constructor_without_unaligned_array_assert()), m_cols(0) {}
inline ei_matrix_storage(int, int, int cols) : m_cols(cols) {}
inline ~ei_matrix_storage() {}
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
@@ -146,9 +162,11 @@ template<typename T, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic,
int m_cols;
public:
inline explicit ei_matrix_storage() : m_data(0), m_rows(0), m_cols(0) {}
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
: m_data(0), m_rows(0), m_cols(0) {}
inline ei_matrix_storage(int size, int rows, int cols)
: m_data(ei_aligned_malloc<T>(size)), m_rows(rows), m_cols(cols) {}
inline ~ei_matrix_storage() { ei_aligned_free(m_data, m_rows*m_cols); }
: m_data(ei_aligned_new<T>(size)), m_rows(rows), m_cols(cols) {}
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, m_rows*m_cols); }
inline void swap(ei_matrix_storage& other)
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
inline int rows(void) const {return m_rows;}
@@ -157,8 +175,8 @@ template<typename T, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic,
{
if(size != m_rows*m_cols)
{
ei_aligned_free(m_data, m_rows*m_cols);
m_data = ei_aligned_malloc<T>(size);
ei_aligned_delete(m_data, m_rows*m_cols);
m_data = ei_aligned_new<T>(size);
}
m_rows = rows;
m_cols = cols;
@@ -174,8 +192,9 @@ template<typename T, int _Rows, int _Options> class ei_matrix_storage<T, Dynamic
int m_cols;
public:
inline explicit ei_matrix_storage() : m_data(0), m_cols(0) {}
inline ei_matrix_storage(int size, int, int cols) : m_data(ei_aligned_malloc<T>(size)), m_cols(cols) {}
inline ~ei_matrix_storage() { ei_aligned_free(m_data, _Rows*m_cols); }
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
inline ei_matrix_storage(int size, int, int cols) : m_data(ei_aligned_new<T>(size)), m_cols(cols) {}
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Rows*m_cols); }
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
inline static int rows(void) {return _Rows;}
inline int cols(void) const {return m_cols;}
@@ -183,8 +202,8 @@ template<typename T, int _Rows, int _Options> class ei_matrix_storage<T, Dynamic
{
if(size != _Rows*m_cols)
{
ei_aligned_free(m_data, _Rows*m_cols);
m_data = ei_aligned_malloc<T>(size);
ei_aligned_delete(m_data, _Rows*m_cols);
m_data = ei_aligned_new<T>(size);
}
m_cols = cols;
}
@@ -199,8 +218,9 @@ template<typename T, int _Cols, int _Options> class ei_matrix_storage<T, Dynamic
int m_rows;
public:
inline explicit ei_matrix_storage() : m_data(0), m_rows(0) {}
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_malloc<T>(size)), m_rows(rows) {}
inline ~ei_matrix_storage() { ei_aligned_free(m_data, _Cols*m_rows); }
inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_new<T>(size)), m_rows(rows) {}
inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Cols*m_rows); }
inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
inline int rows(void) const {return m_rows;}
inline static int cols(void) {return _Cols;}
@@ -208,8 +228,8 @@ template<typename T, int _Cols, int _Options> class ei_matrix_storage<T, Dynamic
{
if(size != m_rows*_Cols)
{
ei_aligned_free(m_data, _Cols*m_rows);
m_data = ei_aligned_malloc<T>(size);
ei_aligned_delete(m_data, _Cols*m_rows);
m_data = ei_aligned_new<T>(size);
}
m_rows = rows;
}

View File

@@ -38,18 +38,8 @@
* \sa MatrixBase::nestByValue()
*/
template<typename ExpressionType>
struct ei_traits<NestByValue<ExpressionType> >
{
typedef typename ExpressionType::Scalar Scalar;
enum {
RowsAtCompileTime = ExpressionType::RowsAtCompileTime,
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
Flags = ExpressionType::Flags,
CoeffReadCost = ExpressionType::CoeffReadCost
};
};
struct ei_traits<NestByValue<ExpressionType> > : public ei_traits<ExpressionType>
{};
template<typename ExpressionType> class NestByValue
: public MatrixBase<NestByValue<ExpressionType> >

View File

@@ -43,16 +43,11 @@
* \sa MatrixBase::part()
*/
template<typename MatrixType, unsigned int Mode>
struct ei_traits<Part<MatrixType, Mode> >
struct ei_traits<Part<MatrixType, Mode> > : ei_traits<MatrixType>
{
typedef typename MatrixType::Scalar Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
Flags = (_MatrixTypeNested::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
};

View File

@@ -573,7 +573,7 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
_res = &res.coeffRef(0);
else
{
_res = ei_aligned_stack_alloc(Scalar,res.size());
_res = ei_aligned_stack_new(Scalar,res.size());
Map<Matrix<Scalar,DestDerived::RowsAtCompileTime,1> >(_res, res.size()) = res;
}
ei_cache_friendly_product_colmajor_times_vector(res.size(),
@@ -583,7 +583,7 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirect
if (!EvalToRes)
{
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
ei_aligned_stack_free(_res, Scalar, res.size());
ei_aligned_stack_delete(Scalar, _res, res.size());
}
}
};
@@ -619,7 +619,7 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
_res = &res.coeffRef(0);
else
{
_res = ei_aligned_stack_alloc(Scalar, res.size());
_res = ei_aligned_stack_new(Scalar, res.size());
Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size()) = res;
}
ei_cache_friendly_product_colmajor_times_vector(res.size(),
@@ -629,7 +629,7 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
if (!EvalToRes)
{
res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
ei_aligned_stack_free(_res, Scalar, res.size());
ei_aligned_stack_delete(Scalar, _res, res.size());
}
}
};
@@ -652,13 +652,13 @@ struct ei_cache_friendly_product_selector<ProductType,LhsRows,RowMajor,HasDirect
_rhs = &product.rhs().const_cast_derived().coeffRef(0);
else
{
_rhs = ei_aligned_stack_alloc(Scalar, product.rhs().size());
_rhs = ei_aligned_stack_new(Scalar, product.rhs().size());
Map<Matrix<Scalar,Rhs::SizeAtCompileTime,1> >(_rhs, product.rhs().size()) = product.rhs();
}
ei_cache_friendly_product_rowmajor_times_vector(&product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
_rhs, product.rhs().size(), res);
if (!UseRhsDirectly) ei_aligned_stack_free(_rhs, Scalar, product.rhs().size());
if (!UseRhsDirectly) ei_aligned_stack_delete(Scalar, _rhs, product.rhs().size());
}
};
@@ -680,13 +680,13 @@ struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCo
_lhs = &product.lhs().const_cast_derived().coeffRef(0);
else
{
_lhs = ei_aligned_stack_alloc(Scalar, product.lhs().size());
_lhs = ei_aligned_stack_new(Scalar, product.lhs().size());
Map<Matrix<Scalar,Lhs::SizeAtCompileTime,1> >(_lhs, product.lhs().size()) = product.lhs();
}
ei_cache_friendly_product_rowmajor_times_vector(&product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
_lhs, product.lhs().size(), res);
if(!UseLhsDirectly) ei_aligned_stack_free(_lhs, Scalar, product.lhs().size());
if(!UseLhsDirectly) ei_aligned_stack_delete(Scalar, _lhs, product.lhs().size());
}
};

View File

@@ -42,7 +42,6 @@ public:
enum {
Vectorization = (int(Derived::Flags)&ActualPacketAccessBit)
&& (int(Derived::Flags)&LinearAccessBit)
&& (int(Derived::SizeAtCompileTime)>2*PacketSize)
? LinearVectorization
: NoVectorization
};
@@ -155,12 +154,13 @@ struct ei_sum_vec_unroller<Derived, Index, Stop, true>
template<typename Derived,
int Vectorization = ei_sum_traits<Derived>::Vectorization,
int Unrolling = ei_sum_traits<Derived>::Unrolling
int Unrolling = ei_sum_traits<Derived>::Unrolling,
int Storage = ei_traits<Derived>::Flags & SparseBit
>
struct ei_sum_impl;
template<typename Derived>
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
struct ei_sum_impl<Derived, NoVectorization, NoUnrolling, IsDense>
{
typedef typename Derived::Scalar Scalar;
static Scalar run(const Derived& mat)
@@ -178,12 +178,12 @@ struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
};
template<typename Derived>
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling>
struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling, IsDense>
: public ei_sum_novec_unroller<Derived, 0, Derived::SizeAtCompileTime>
{};
template<typename Derived>
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling,IsDense>
{
typedef typename Derived::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
@@ -228,14 +228,21 @@ struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
};
template<typename Derived>
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling, IsDense>
{
typedef typename Derived::Scalar Scalar;
typedef typename ei_packet_traits<Scalar>::type PacketScalar;
enum {
PacketSize = ei_packet_traits<Scalar>::size,
Size = Derived::SizeAtCompileTime,
VectorizationSize = (Size / PacketSize) * PacketSize
};
static Scalar run(const Derived& mat)
{
return ei_predux(
ei_sum_vec_unroller<Derived, 0, Derived::SizeAtCompileTime>::run(mat)
);
Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, VectorizationSize>::run(mat));
if (VectorizationSize != Size)
res += ei_sum_novec_unroller<Derived, VectorizationSize, Size-VectorizationSize>::run(mat);
return res;
}
};

View File

@@ -223,15 +223,13 @@ enum {
};
enum {
Matrix_ColMajor = 0,
Matrix_RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
ColMajor = 0,
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
/** \internal Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be
requested to be aligned) */
ColMajor = Matrix_ColMajor, // deprecated
RowMajor = Matrix_RowMajor, // deprecated
Matrix_DontAlign = 0,
/** \internal Align the matrix itself */
Matrix_AutoAlign = 0x2
DontAlign = 0,
/** \internal Align the matrix itself if it is vectorizable fixed-size */
AutoAlign = 0x2
};
enum {

View File

@@ -1,9 +1,5 @@
#ifndef EIGEN_DISABLEMSVCWARNINGS_H
#define EIGEN_DISABLEMSVCWARNINGS_H
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4181 4244 4127 4211 )
#endif
#endif // EIGEN_DISABLEMSVCWARNINGS_H

View File

@@ -1,8 +1,4 @@
#ifndef EIGEN_ENABLEMSVCWARNINGS_H
#define EIGEN_ENABLEMSVCWARNINGS_H
#ifdef _MSC_VER
#pragma warning( pop )
#endif
#endif // EIGEN_ENABLEMSVCWARNINGS_H

View File

@@ -29,7 +29,7 @@ template<typename T> struct ei_traits;
template<typename T> struct NumTraits;
template<typename _Scalar, int _Rows, int _Cols,
int _Options = EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION | Matrix_AutoAlign,
int _Options = EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION | AutoAlign,
int _MaxRows = _Rows, int _MaxCols = _Cols> class Matrix;
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged;

View File

@@ -37,9 +37,9 @@
EIGEN_MINOR_VERSION>=z))))
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Matrix_RowMajor
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor
#else
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Matrix_ColMajor
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ColMajor
#endif
/** \internal Defines the maximal loop size to enable meta unrolling of loops.

View File

@@ -3,6 +3,7 @@
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -26,87 +27,170 @@
#ifndef EIGEN_MEMORY_H
#define EIGEN_MEMORY_H
#ifdef __linux
// it seems we cannot assume posix_memalign is defined in the stdlib header
extern "C" int posix_memalign (void **, size_t, size_t) throw ();
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN64)
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
#else
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
#endif
struct ei_byte_forcing_aligned_malloc
{
unsigned char c; // sizeof must be 1.
};
template<typename T> struct ei_force_aligned_malloc { enum { ret = 0 }; };
template<> struct ei_force_aligned_malloc<ei_byte_forcing_aligned_malloc> { enum { ret = 1 }; };
#if (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))
#define EIGEN_HAS_POSIX_MEMALIGN 1
#else
#define EIGEN_HAS_POSIX_MEMALIGN 0
#endif
/** \internal allocates \a size * sizeof(\a T) bytes. If vectorization is enabled and T is such that a packet
* containts more than one T, then the returned pointer is guaranteed to have 16 bytes alignment.
#ifdef EIGEN_VECTORIZE_SSE
#define EIGEN_HAS_MM_MALLOC 1
#else
#define EIGEN_HAS_MM_MALLOC 0
#endif
/** \internal like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
* Fast, but wastes 16 additional bytes of memory.
* Does not throw any exception.
*/
inline void* ei_handmade_aligned_malloc(size_t size)
{
void *original = malloc(size+16);
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
*(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned;
}
/** \internal frees memory allocated with ei_handmade_aligned_malloc */
inline void ei_handmade_aligned_free(void *ptr)
{
if(ptr)
free(*(reinterpret_cast<void**>(ptr) - 1));
}
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
*/
template<typename T>
inline T* ei_aligned_malloc(size_t size)
inline void* ei_aligned_malloc(size_t size)
{
if(ei_packet_traits<T>::size>1 || ei_force_aligned_malloc<T>::ret)
{
void *void_result;
#ifdef __linux
#ifdef EIGEN_EXCEPTIONS
const int failed =
#endif
posix_memalign(&void_result, 16, size*sizeof(T));
#ifdef EIGEN_NO_MALLOC
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *result;
#if EIGEN_HAS_POSIX_MEMALIGN && !EIGEN_MALLOC_ALREADY_ALIGNED
#ifdef EIGEN_EXCEPTIONS
const int failed =
#endif
posix_memalign(&result, 16, size);
#else
#if EIGEN_MALLOC_ALREADY_ALIGNED
result = malloc(size);
#elif EIGEN_HAS_MM_MALLOC
result = _mm_malloc(size, 16);
#elif (defined _MSC_VER)
result = _aligned_malloc(size, 16);
#else
#ifdef _MSC_VER
void_result = _aligned_malloc(size*sizeof(T), 16);
#elif defined(__APPLE__)
void_result = malloc(size*sizeof(T)); // Apple's malloc() already returns aligned ptrs
#else
void_result = _mm_malloc(size*sizeof(T), 16);
#endif
#ifdef EIGEN_EXCEPTIONS
const int failed = (void_result == 0);
#endif
result = ei_handmade_aligned_malloc(size);
#endif
#ifdef EIGEN_EXCEPTIONS
if(failed)
throw std::bad_alloc();
const int failed = (result == 0);
#endif
// if the user uses Eigen on some fancy scalar type such as multiple-precision numbers,
// and this type has a custom operator new, then we want to honor this operator new!
// so when we use C functions to allocate memory, we must be careful to call manually the constructor using
// the special placement-new syntax.
return new(void_result) T[size];
}
else
return new T[size]; // here we really want a new, not a malloc. Justification: if the user uses Eigen on
// some fancy scalar type such as multiple-precision numbers, and this type has a custom operator new,
// then we want to honor this operator new! Anyway this type won't have vectorization so the vectorizing path
// is irrelevant here. Yes, we should say somewhere in the docs that if the user uses a custom scalar type then
// he can't have both vectorization and a custom operator new on his scalar type.
#endif
#ifdef EIGEN_EXCEPTIONS
if(failed)
throw std::bad_alloc();
#endif
return result;
}
/** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
*/
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
{
return ei_aligned_malloc(size);
}
template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
{
#ifdef EIGEN_NO_MALLOC
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *void_result = malloc(size);
#ifdef EIGEN_EXCEPTIONS
if(!void_result) throw std::bad_alloc();
#endif
return void_result;
}
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
* On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
* The default constructor of T is called.
*/
template<typename T> inline T* ei_aligned_new(size_t size)
{
void *void_result = ei_aligned_malloc(sizeof(T)*size);
return ::new(void_result) T[size];
}
template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t size)
{
void *void_result = ei_conditional_aligned_malloc<Align>(sizeof(T)*size);
return ::new(void_result) T[size];
}
/** \internal free memory allocated with ei_aligned_malloc
* The \a size parameter is used to determine on how many elements to call the destructor. If you don't
* want any destructor to be called, just pass 0.
*/
template<typename T>
inline void ei_aligned_free(T* ptr, size_t size)
inline void ei_aligned_free(void *ptr)
{
if (ei_packet_traits<T>::size>1 || ei_force_aligned_malloc<T>::ret)
{
// need to call manually the dtor in case T is some user-defined fancy numeric type.
// always destruct an array starting from the end.
while(size) ptr[--size].~T();
#if defined(__linux)
free(ptr);
#elif defined(__APPLE__)
free(ptr);
#elif defined(_MSC_VER)
_aligned_free(ptr);
#else
_mm_free(ptr);
#endif
}
else
delete[] ptr;
#if EIGEN_MALLOC_ALREADY_ALIGNED
free(ptr);
#elif EIGEN_HAS_POSIX_MEMALIGN
free(ptr);
#elif EIGEN_HAS_MM_MALLOC
_mm_free(ptr);
#elif defined(_MSC_VER)
_aligned_free(ptr);
#else
ei_handmade_aligned_free(ptr);
#endif
}
/** \internal free memory allocated with ei_conditional_aligned_malloc
*/
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
{
ei_aligned_free(ptr);
}
template<> inline void ei_conditional_aligned_free<false>(void *ptr)
{
free(ptr);
}
/** \internal delete the elements of an array.
* The \a size parameters tells on how many objects to call the destructor of T.
*/
template<typename T> inline void ei_delete_elements_of_array(T *ptr, size_t size)
{
// always destruct an array starting from the end.
while(size) ptr[--size].~T();
}
/** \internal delete objects constructed with ei_aligned_new
* The \a size parameters tells on how many objects to call the destructor of T.
*/
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
{
ei_delete_elements_of_array<T>(ptr, size);
ei_aligned_free(ptr);
}
/** \internal delete objects constructed with ei_conditional_aligned_new
* The \a size parameters tells on how many objects to call the destructor of T.
*/
template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
{
ei_delete_elements_of_array<T>(ptr, size);
ei_conditional_aligned_free<Align>(ptr);
}
/** \internal \returns the number of elements which have to be skipped such that data are 16 bytes aligned */
@@ -124,10 +208,10 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
}
/** \internal
* ei_aligned_stack_alloc(TYPE,SIZE) allocates an aligned buffer of sizeof(TYPE)*SIZE bytes
* on the stack if sizeof(TYPE)*SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
* ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
* on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
* Otherwise the memory is allocated on the heap.
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,TYPE,SIZE).
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
* \code
* float * data = ei_aligned_stack_alloc(float,array.size());
* // ...
@@ -135,18 +219,41 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
* \endcode
*/
#ifdef __linux__
#define ei_aligned_stack_alloc(TYPE,SIZE) ((sizeof(TYPE)*(SIZE)>EIGEN_STACK_ALLOCATION_LIMIT) \
? ei_aligned_malloc<TYPE>(SIZE) \
: (TYPE*)alloca(sizeof(TYPE)*(SIZE)))
#define ei_aligned_stack_free(PTR,TYPE,SIZE) if (sizeof(TYPE)*SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR,SIZE)
#define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
? alloca(SIZE) \
: ei_aligned_malloc(SIZE)
#define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR)
#else
#define ei_aligned_stack_alloc(TYPE,SIZE) ei_aligned_malloc<TYPE>(SIZE)
#define ei_aligned_stack_free(PTR,TYPE,SIZE) ei_aligned_free(PTR,SIZE)
#define ei_aligned_stack_alloc(SIZE) ei_aligned_malloc(SIZE)
#define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
#endif
/** \class WithAlignedOperatorNew
#define ei_aligned_stack_new(TYPE,SIZE) ::new(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)) TYPE[SIZE]
#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_delete_elements_of_array<TYPE>(PTR, SIZE); \
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
/** Qt <= 4.4 has a bug where it calls new(ptr) T instead of ::new(ptr) T.
* This fails as we overload other operator new but not this one. What Qt really means is placement new.
* Since this is getting used only with fixed-size Eigen matrices where the ctor does nothing, it is OK to
* emulate placement new by just returning the ptr -- no need to call ctors. Good, because we don't know the
* class in this macro. So this can safely be used for QVector<Eigen::Vector4f> but definitely not for
* QVector<Eigen::VectorXf>.
*
* \brief Enforces instances of inherited classes to be 16 bytes aligned when allocated with operator new
* This macro will go away as soon as Qt >= 4.5 is prevalent -- most likely it should go away in Eigen 2.1.
*/
#ifdef EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW \
void *operator new(size_t, void *ptr) throw() { \
return ptr; \
} \
void *operator new[](size_t, void *ptr) throw() { \
return ptr; \
}
#else
#define EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
#endif
/** \brief Overloads the operator new and delete of the class Type with operators that are aligned if NeedsToAlign is true
*
* When Eigen's explicit vectorization is enabled, Eigen assumes that some fixed sizes types are aligned
* on a 16 bytes boundary. Those include all Matrix types having a sizeof multiple of 16 bytes, e.g.:
@@ -173,7 +280,8 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
* overloading the operator new to return aligned data when the vectorization is enabled.
* Here is a similar safe example:
* \code
* struct Foo : public WithAlignedOperatorNew {
* struct Foo {
* EIGEN_MAKE_ALIGNED_OPERATOR_NEW
* char dummy;
* Vector4f some_vector;
* };
@@ -183,74 +291,110 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
*
* \sa class ei_new_allocator
*/
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
void *operator new(size_t size) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void *operator new[](size_t size) throw() { \
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
} \
void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
EIGEN_WORKAROUND_FOR_QT_BUG_CALLING_WRONG_OPERATOR_NEW
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
/** Deprecated, use the EIGEN_MAKE_ALIGNED_OPERATOR_NEW macro instead in your own class */
struct WithAlignedOperatorNew
{
void *operator new(size_t size) throw()
{
return ei_aligned_malloc<ei_byte_forcing_aligned_malloc>(size);
}
void *operator new[](size_t size) throw()
{
return ei_aligned_malloc<ei_byte_forcing_aligned_malloc>(size);
}
void operator delete(void * ptr) { ei_aligned_free(static_cast<ei_byte_forcing_aligned_malloc *>(ptr), 0); }
void operator delete[](void * ptr) { ei_aligned_free(static_cast<ei_byte_forcing_aligned_malloc *>(ptr), 0); }
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
template<typename T, int SizeAtCompileTime,
bool NeedsToAlign = (SizeAtCompileTime!=Dynamic) && ((sizeof(T)*SizeAtCompileTime)%16==0)>
struct ei_with_aligned_operator_new : public WithAlignedOperatorNew {};
template<typename T, int SizeAtCompileTime>
struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {};
/** \class ei_new_allocator
*
* \brief stl compatible allocator to use with with fixed-size vector and matrix types
*
* STL allocator simply wrapping operators new[] and delete[]. Unlike GCC's default new_allocator,
* ei_new_allocator call operator new on the type \a T and not the general new operator ignoring
* overloaded version of operator new.
*
* Example:
* \code
* // Vector4f requires 16 bytes alignment:
* std::vector<Vector4f,ei_new_allocator<Vector4f> > dataVec4;
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
* std::vector<Vector3f> dataVec3;
*
* struct Foo : WithAlignedOperatorNew {
* char dummy;
* Vector4f some_vector;
* };
* std::vector<Foo,ei_new_allocator<Foo> > dataFoo;
* \endcode
*
* \sa class WithAlignedOperatorNew
*/
template<typename T> class ei_new_allocator
/** \class aligned_allocator
*
* \brief stl compatible allocator to use with with 16 byte aligned types
*
* Example:
* \code
* // Matrix4f requires 16 bytes alignment:
* std::map< int, Matrix4f, std::less<int>, aligned_allocator<Matrix4f> > my_map_mat4;
* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
* std::map< int, Vector3f > my_map_vec3;
* \endcode
*
*/
template<class T>
class aligned_allocator
{
public:
typedef T value_type;
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template<typename OtherType>
template<class U>
struct rebind
{ typedef ei_new_allocator<OtherType> other; };
{
typedef aligned_allocator<U> other;
};
T* address(T& ref) const { return &ref; }
const T* address(const T& ref) const { return &ref; }
T* allocate(size_t size, const void* = 0) { return new T[size]; }
void deallocate(T* ptr, size_t) { delete[] ptr; }
size_t max_size() const { return size_t(-1) / sizeof(T); }
// FIXME I'm note sure about this construction...
void construct(T* ptr, const T& refObj) { ::new(ptr) T(refObj); }
void destroy(T* ptr) { ptr->~T(); }
pointer address( reference value ) const
{
return &value;
}
const_pointer address( const_reference value ) const
{
return &value;
}
aligned_allocator() throw()
{
}
aligned_allocator( const aligned_allocator& ) throw()
{
}
template<class U>
aligned_allocator( const aligned_allocator<U>& ) throw()
{
}
~aligned_allocator() throw()
{
}
size_type max_size() const throw()
{
return std::numeric_limits<size_type>::max();
}
pointer allocate( size_type num, const_pointer* hint = 0 )
{
static_cast<void>( hint ); // suppress unused variable warning
return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
}
void construct( pointer p, const T& value )
{
::new( p ) T( value );
}
void destroy( pointer p )
{
p->~T();
}
void deallocate( pointer p, size_type /*num*/ )
{
ei_aligned_free( p );
}
};
#endif // EIGEN_MEMORY_H

View File

@@ -89,11 +89,11 @@ template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxC
class ei_compute_matrix_flags
{
enum {
row_major_bit = Options&Matrix_RowMajor ? RowMajorBit : 0,
row_major_bit = Options&RowMajor ? RowMajorBit : 0,
inner_max_size = row_major_bit ? MaxCols : MaxRows,
is_big = inner_max_size == Dynamic,
is_packet_size_multiple = (Cols*Rows) % ei_packet_traits<Scalar>::size == 0,
aligned_bit = ((Options&Matrix_AutoAlign) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
aligned_bit = ((Options&AutoAlign) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
};
@@ -117,7 +117,7 @@ template<typename T> struct ei_eval<T,IsDense>
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
Matrix_AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? Matrix_RowMajor : Matrix_ColMajor),
AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;
@@ -138,7 +138,7 @@ template<typename T> struct ei_plain_matrix_type
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
Matrix_AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? Matrix_RowMajor : Matrix_ColMajor),
AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;
@@ -151,7 +151,7 @@ template<typename T> struct ei_plain_matrix_type_column_major
typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime,
Matrix_AutoAlign | Matrix_ColMajor,
AutoAlign | ColMajor,
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime
> type;

View File

@@ -39,10 +39,9 @@
*/
template <typename _Scalar, int _AmbientDim>
class AlignedBox
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
{
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;

View File

@@ -147,7 +147,7 @@ public:
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
{
m_axis = other.axis().template cast<Scalar>();
m_angle = other.angle();
m_angle = Scalar(other.angle());
}
/** \returns \c true if \c *this is approximately equal to \a other, within the precision

View File

@@ -45,10 +45,9 @@
*/
template <typename _Scalar, int _AmbientDim>
class Hyperplane
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
{
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;

View File

@@ -41,10 +41,9 @@
*/
template <typename _Scalar, int _AmbientDim>
class ParametrizedLine
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
enum { AmbientDimAtCompileTime = _AmbientDim };
typedef _Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;

View File

@@ -59,19 +59,19 @@ template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
template<typename _Scalar>
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
, public ei_with_aligned_operator_new<_Scalar,4>
{
typedef RotationBase<Quaternion<_Scalar>,3> Base;
typedef Matrix<_Scalar, 4, 1> Coefficients;
Coefficients m_coeffs;
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 */
@@ -110,8 +110,11 @@ public:
inline Coefficients& coeffs() { return m_coeffs; }
/** Default constructor and initializing an identity quaternion. */
inline Quaternion()
{ m_coeffs << 0, 0, 0, 1; }
inline Quaternion() {}
inline Quaternion(ei_constructor_without_unaligned_array_assert)
: m_coeffs(ei_constructor_without_unaligned_array_assert()) {}
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
* its four coefficients \a w, \a x, \a y and \a z.
@@ -149,7 +152,7 @@ public:
/** \sa Quaternion::Identity(), MatrixBase::setIdentity()
*/
inline Quaternion& setIdentity() { m_coeffs << 1, 0, 0, 0; return *this; }
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()
@@ -214,6 +217,8 @@ public:
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 GeometryModule
@@ -354,7 +359,7 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
// set to identity
this->w() = 1; this->vec().setZero();
}
Scalar s = ei_sqrt((1+c)*2);
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
Scalar invs = Scalar(1)/s;
this->vec() = axis * invs;
this->w() = s * Scalar(0.5);
@@ -459,7 +464,7 @@ struct ei_quaternion_assign_impl<Other,3,3>
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) + 1.0);
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;

View File

@@ -114,7 +114,7 @@ public:
template<typename OtherScalarType>
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
{
m_angle = other.angle();
m_angle = Scalar(other.angle());
}
/** \returns \c true if \c *this is approximately equal to \a other, within the precision

View File

@@ -41,9 +41,9 @@
*/
template<typename _Scalar, int _Dim>
class Scaling
: public ei_with_aligned_operator_new<_Scalar,_Dim>
{
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 */

View File

@@ -61,10 +61,9 @@ struct ei_transform_product_impl;
*/
template<typename _Scalar, int _Dim>
class Transform
: public ei_with_aligned_operator_new<_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)>
{
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
@@ -95,8 +94,13 @@ public:
/** Default constructor without initialization of the coefficients. */
inline Transform() { }
inline Transform(ei_constructor_without_unaligned_array_assert)
: m_matrix(ei_constructor_without_unaligned_array_assert()) {}
inline Transform(const Transform& other)
{ m_matrix = other.m_matrix; }
{
m_matrix = other.m_matrix;
}
inline explicit Transform(const TranslationType& t) { *this = t; }
inline explicit Transform(const ScalingType& s) { *this = s; }

View File

@@ -41,9 +41,9 @@
*/
template<typename _Scalar, int _Dim>
class Translation
: public ei_with_aligned_operator_new<_Scalar,_Dim>
{
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 */

View File

@@ -282,7 +282,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
int n = nn-1;
int low = 0;
int high = nn-1;
Scalar eps = pow(2.0,-52.0);
Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
Scalar exshift = 0.0;
Scalar p=0,q=0,r=0,s=0,z=0,t,w,x,y;
@@ -328,7 +328,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
else if (l == n-1) // Two roots found
{
w = matH.coeff(n,n-1) * matH.coeff(n-1,n);
p = (matH.coeff(n-1,n-1) - matH.coeff(n,n)) / 2.0;
p = (matH.coeff(n-1,n-1) - matH.coeff(n,n)) * Scalar(0.5);
q = p * p + w;
z = ei_sqrt(ei_abs(q));
matH.coeffRef(n,n) = matH.coeff(n,n) + exshift;
@@ -405,25 +405,25 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
for (int i = low; i <= n; ++i)
matH.coeffRef(i,i) -= x;
s = ei_abs(matH.coeff(n,n-1)) + ei_abs(matH.coeff(n-1,n-2));
x = y = 0.75 * s;
w = -0.4375 * s * s;
x = y = Scalar(0.75) * s;
w = Scalar(-0.4375) * s * s;
}
// MATLAB's new ad hoc shift
if (iter == 30)
{
s = (y - x) / 2.0;
s = Scalar((y - x) / 2.0);
s = s * s + w;
if (s > 0)
{
s = ei_sqrt(s);
if (y < x)
s = -s;
s = x - w / ((y - x) / 2.0 + s);
s = Scalar(x - w / ((y - x) / 2.0 + s));
for (int i = low; i <= n; ++i)
matH.coeffRef(i,i) -= s;
exshift += s;
x = y = w = 0.964;
x = y = w = Scalar(0.964);
}
}
@@ -469,7 +469,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
if (k != m) {
p = matH.coeff(k,k-1);
q = matH.coeff(k+1,k-1);
r = (notlast ? matH.coeff(k+2,k-1) : 0.0);
r = notlast ? matH.coeff(k+2,k-1) : Scalar(0);
x = ei_abs(p) + ei_abs(q) + ei_abs(r);
if (x != 0.0)
{
@@ -647,7 +647,7 @@ void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
x = matH.coeff(i,i+1);
y = matH.coeff(i+1,i);
vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
vi = (m_eivalues.coeff(i).real() - p) * 2.0 * q;
vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
if ((vr == 0.0) && (vi == 0.0))
vr = eps * norm * (ei_abs(w) + ei_abs(q) + ei_abs(x) + ei_abs(y) + ei_abs(z));

View File

@@ -334,7 +334,7 @@ MatrixBase<Derived>::operatorNorm() const
template<typename RealScalar, typename Scalar>
static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int start, int end, Scalar* matrixQ, int n)
{
RealScalar td = (diag[end-1] - diag[end])*0.5;
RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
RealScalar e2 = ei_abs2(subdiag[end-1]);
RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * ei_sqrt(td*td + e2));
RealScalar x = diag[start] - mu;
@@ -357,10 +357,12 @@ static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int st
subdiag[k - 1] = c * subdiag[k-1] - s * z;
x = subdiag[k];
z = -s * subdiag[k+1];
if (k < end - 1)
{
z = -s * subdiag[k+1];
subdiag[k + 1] = c * subdiag[k+1];
}
// apply the givens rotation to the unit matrix Q = Q * G
// G only modifies the two columns k and k+1

View File

@@ -208,7 +208,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
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) = 1.0 + m_matU(k,k);
m_matU(k,k) = Scalar(1) + m_matU(k,k);
if (k-1>0)
m_matU.col(k).start(k-1).setZero();
}
@@ -242,7 +242,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
// Main iteration loop for the singular values.
int pp = p-1;
int iter = 0;
Scalar eps(pow(2.0,-52.0));
Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
while (p > 0)
{
int k=0;
@@ -260,7 +260,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
// 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--)
for (k = p-2; k >= -1; --k)
{
if (k == -1)
break;
@@ -277,11 +277,11 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
else
{
int ks;
for (ks = p-1; ks >= k; ks--)
for (ks = p-1; ks >= k; --ks)
{
if (ks == k)
break;
Scalar t( (ks != p ? ei_abs(e[ks]) : 0.) + (ks != k+1 ? ei_abs(e[ks-1]) : 0.));
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;
@@ -313,9 +313,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
{
Scalar f(e[p-2]);
e[p-2] = 0.0;
for (j = p-2; j >= k; j--)
for (j = p-2; j >= k; --j)
{
Scalar t(hypot(m_sigma[j],f));
Scalar t(ei_hypot(m_sigma[j],f));
Scalar cs(m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -344,7 +344,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
e[k-1] = 0.0;
for (j = k; j < p; ++j)
{
Scalar t(hypot(m_sigma[j],f));
Scalar t(ei_hypot(m_sigma[j],f));
Scalar cs( m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -375,7 +375,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
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)/2.0;
Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/Scalar(2);
Scalar c = (sp*epm1)*(sp*epm1);
Scalar shift = 0.0;
if ((b != 0.0) || (c != 0.0))
@@ -392,7 +392,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
for (j = k; j < p-1; ++j)
{
Scalar t = hypot(f,g);
Scalar t = ei_hypot(f,g);
Scalar cs = f/t;
Scalar sn = g/t;
if (j != k)
@@ -410,7 +410,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
m_matV(i,j) = t;
}
}
t = hypot(f,g);
t = ei_hypot(f,g);
cs = f/t;
sn = g/t;
m_sigma[j] = t;
@@ -439,7 +439,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
// Make the singular values positive.
if (m_sigma[k] <= 0.0)
{
m_sigma[k] = (m_sigma[k] < 0.0 ? -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);
}

View File

@@ -33,21 +33,21 @@ class MatrixBase<Derived>::InnerIterator
{
typedef typename Derived::Scalar Scalar;
public:
InnerIterator(const Derived& mat, int outer)
EIGEN_STRONG_INLINE InnerIterator(const Derived& mat, int outer)
: m_matrix(mat), m_inner(0), m_outer(outer), m_end(mat.rows())
{}
Scalar value() const
EIGEN_STRONG_INLINE Scalar value() const
{
return (Derived::Flags&RowMajorBit) ? m_matrix.coeff(m_outer, m_inner)
: m_matrix.coeff(m_inner, m_outer);
}
InnerIterator& operator++() { m_inner++; return *this; }
EIGEN_STRONG_INLINE InnerIterator& operator++() { m_inner++; return *this; }
int index() const { return m_inner; }
EIGEN_STRONG_INLINE int index() const { return m_inner; }
operator bool() const { return m_inner < m_end && m_inner>=0; }
EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; }
protected:
const Derived& m_matrix;
@@ -61,7 +61,7 @@ class Transpose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
{
public:
InnerIterator(const Transpose& trans, int outer)
EIGEN_STRONG_INLINE InnerIterator(const Transpose& trans, int outer)
: MatrixType::InnerIterator(trans.m_matrix, outer)
{}
};
@@ -74,7 +74,7 @@ class Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus>
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
InnerIterator(const Block& block, int outer)
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
@@ -84,24 +84,24 @@ class Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus>
++m_iter;
}
InnerIterator& operator++()
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
++m_iter;
return *this;
}
Scalar value() const { return m_iter.value(); }
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
int index() const { return m_iter.index() - m_offset; }
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
operator bool() const { return m_iter && m_iter.index()<m_end; }
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
protected:
MatrixTypeIterator m_iter;
int m_start;
int m_end;
int m_offset;
};
};
template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
class Block<MatrixType, BlockRows, BlockCols, PacketAccess, IsSparse>::InnerIterator
@@ -111,7 +111,7 @@ class Block<MatrixType, BlockRows, BlockCols, PacketAccess, IsSparse>::InnerIter
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
InnerIterator(const Block& block, int outer)
EIGEN_STRONG_INLINE InnerIterator(const Block& block, int outer)
: m_iter(block.m_matrix,(Block::Flags&RowMajor) ? block.m_startRow.value() + outer : block.m_startCol.value() + outer),
m_start( (Block::Flags&RowMajor) ? block.m_startCol.value() : block.m_startRow.value()),
m_end(m_start + ((Block::Flags&RowMajor) ? block.m_blockCols.value() : block.m_blockRows.value())),
@@ -121,17 +121,17 @@ class Block<MatrixType, BlockRows, BlockCols, PacketAccess, IsSparse>::InnerIter
++m_iter;
}
InnerIterator& operator++()
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
++m_iter;
return *this;
}
Scalar value() const { return m_iter.value(); }
EIGEN_STRONG_INLINE Scalar value() const { return m_iter.value(); }
int index() const { return m_iter.index() - m_offset; }
EIGEN_STRONG_INLINE int index() const { return m_iter.index() - m_offset; }
operator bool() const { return m_iter && m_iter.index()<m_end; }
EIGEN_STRONG_INLINE operator bool() const { return m_iter && m_iter.index()<m_end; }
protected:
MatrixTypeIterator m_iter;
@@ -148,13 +148,13 @@ class CwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
public:
InnerIterator(const CwiseUnaryOp& unaryOp, int outer)
EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOp& unaryOp, int outer)
: m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor), m_id(-1)
{
this->operator++();
}
InnerIterator& operator++()
EIGEN_STRONG_INLINE InnerIterator& operator++()
{
if (m_iter)
{
@@ -169,11 +169,11 @@ class CwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
return *this;
}
Scalar value() const { return m_value; }
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
int index() const { return m_id; }
EIGEN_STRONG_INLINE int index() const { return m_id; }
operator bool() const { return m_id>=0; }
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
protected:
MatrixTypeIterator m_iter;
@@ -182,23 +182,54 @@ class CwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
int m_id;
};
template<typename T> struct ei_is_scalar_product { enum { ret = false }; };
template<typename T> struct ei_is_scalar_product<ei_scalar_product_op<T> > { enum { ret = true }; };
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator;
template<typename BinaryOp, typename Lhs, typename Rhs>
class CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
: public CwiseBinaryOpInnerIterator<BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
{
typedef CwiseBinaryOpInnerIterator<
BinaryOp,Lhs,Rhs, typename CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator> Base;
public:
typedef typename CwiseBinaryOp::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
// public:
EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOp& binOp, int outer)
: Base(binOp.m_lhs,binOp.m_rhs,binOp.m_functor,outer)
{}
};
template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator
{
typedef CwiseBinaryOp<BinaryOp,Lhs,Rhs> ExpressionType;
typedef typename ExpressionType::Scalar Scalar;
typedef typename ei_traits<ExpressionType>::_LhsNested _LhsNested;
// typedef typename ei_traits<ExpressionType>::LhsIterator LhsIterator;
typedef typename ei_traits<ExpressionType>::_RhsNested _RhsNested;
// typedef typename ei_traits<ExpressionType>::RhsIterator RhsIterator;
// typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
// typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
// enum { IsProduct = ei_is_scalar_product<BinaryOp>::ret };
public:
InnerIterator(const CwiseBinaryOp& binOp, int outer)
: m_lhsIter(binOp.m_lhs,outer), m_rhsIter(binOp.m_rhs,outer), m_functor(binOp.m_functor), m_id(-1)
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const _LhsNested& lhs, const _RhsNested& rhs,
const BinaryOp& functor, int outer)
: m_lhsIter(lhs,outer), m_rhsIter(rhs,outer), m_functor(functor), m_id(-1)
{
this->operator++();
}
InnerIterator& operator++()
EIGEN_STRONG_INLINE Derived& operator++()
{
if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
{
@@ -223,14 +254,14 @@ class CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
{
m_id = -1;
}
return *this;
return *static_cast<Derived*>(this);
}
Scalar value() const { return m_value; }
EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
int index() const { return m_id; }
EIGEN_STRONG_INLINE int index() const { return m_id; }
operator bool() const { return m_id>=0; }
EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
protected:
LhsIterator m_lhsIter;
@@ -239,5 +270,65 @@ class CwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
Scalar m_value;
int m_id;
};
/*
template<typename T, typename Lhs, typename Rhs, typename Derived>
class CwiseBinaryOpInnerIterator<ei_scalar_product_op<T>,Lhs,Rhs,Derived>
{
typedef typename CwiseBinaryOp::Scalar Scalar;
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename _LhsNested::InnerIterator LhsIterator;
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
typedef typename _RhsNested::InnerIterator RhsIterator;
public:
EIGEN_STRONG_INLINE CwiseBinaryOpInnerIterator(const CwiseBinaryOp& binOp, int outer)
: m_lhsIter(binOp.m_lhs,outer), m_rhsIter(binOp.m_rhs,outer), m_functor(binOp.m_functor)//, m_id(-1)
{
//this->operator++();
while (m_lhsIter && m_rhsIter && m_lhsIter.index() != m_rhsIter.index())
{
if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
}
EIGEN_STRONG_INLINE Derived& operator++()
{
// m_id = -1;
asm("#beginwhile");
while (m_lhsIter && m_rhsIter)
{
if (m_lhsIter.index() == m_rhsIter.index())
{
// m_id = m_lhsIter.index();
//m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
++m_lhsIter;
++m_rhsIter;
break;
}
else if (m_lhsIter.index() < m_rhsIter.index())
++m_lhsIter;
else
++m_rhsIter;
}
asm("#endwhile");
return *static_cast<Derived*>(this);
}
EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter && m_rhsIter; }
protected:
LhsIterator m_lhsIter;
RhsIterator m_rhsIter;
const BinaryOp& m_functor;
// Scalar m_value;
// int m_id;
};*/
#endif // EIGEN_COREITERATORS_H

View File

@@ -192,7 +192,7 @@ void SparseLDLT<MatrixType,Backend>::_symbolic(const MatrixType& a)
m_matrix.resize(size, size);
m_parent.resize(size);
m_nonZerosPerCol.resize(size);
int * tags = ei_aligned_stack_alloc(int, size);
int * tags = ei_aligned_stack_new(int, size);
const int* Ap = a._outerIndexPtr();
const int* Ai = a._innerIndexPtr();
@@ -238,7 +238,7 @@ void SparseLDLT<MatrixType,Backend>::_symbolic(const MatrixType& a)
Lp[k+1] = Lp[k] + m_nonZerosPerCol[k];
m_matrix.resizeNonZeros(Lp[size]);
ei_aligned_stack_free(tags, int, size);
ei_aligned_stack_delete(int, tags, size);
}
template<typename MatrixType, int Backend>
@@ -257,9 +257,9 @@ bool SparseLDLT<MatrixType,Backend>::_numeric(const MatrixType& a)
Scalar* Lx = m_matrix._valuePtr();
m_diag.resize(size);
Scalar * y = ei_aligned_stack_alloc(Scalar, size);
int * pattern = ei_aligned_stack_alloc(int, size);
int * tags = ei_aligned_stack_alloc(int, size);
Scalar * y = ei_aligned_stack_new(Scalar, size);
int * pattern = ei_aligned_stack_new(int, size);
int * tags = ei_aligned_stack_new(int, size);
const int* P = 0;
const int* Pinv = 0;
@@ -315,9 +315,9 @@ bool SparseLDLT<MatrixType,Backend>::_numeric(const MatrixType& a)
}
}
ei_aligned_stack_free(y, Scalar, size);
ei_aligned_stack_free(pattern, int, size);
ei_aligned_stack_free(tags, int, size);
ei_aligned_stack_delete(Scalar, y, size);
ei_aligned_stack_delete(int, pattern, size);
ei_aligned_stack_delete(int, tags, size);
return ok; /* success, diagonal of D is all nonzero */
}

View File

@@ -361,14 +361,14 @@ class SparseMatrix
{
EIGEN_DBG_SPARSE(
s << "Nonzero entries:\n";
for (unsigned int i=0; i<m.nonZeros(); ++i)
for (int i=0; i<m.nonZeros(); ++i)
{
s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
}
s << std::endl;
s << std::endl;
s << "Column pointers:\n";
for (unsigned int i=0; i<m.cols(); ++i)
for (int i=0; i<m.cols(); ++i)
{
s << m.m_outerIndex[i] << " ";
}

View File

@@ -167,6 +167,49 @@ class SparseMatrixBase : public MatrixBase<Derived>
return s;
}
// template<typename OtherDerived>
// Scalar dot(const MatrixBase<OtherDerived>& other) const
// {
// EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
// EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
// EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
//
// ei_assert(derived().size() == other.size());
// // short version, but the assembly looks more complicated because
// // of the CwiseBinaryOp iterator complexity
// // return res = (derived().cwise() * other.derived().conjugate()).sum();
//
// // optimized, generic version
// typename Derived::InnerIterator i(derived(),0);
// typename OtherDerived::InnerIterator j(other.derived(),0);
// Scalar res = 0;
// while (i && j)
// {
// if (i.index()==j.index())
// {
// // std::cerr << i.value() << " * " << j.value() << "\n";
// res += i.value() * ei_conj(j.value());
// ++i; ++j;
// }
// else if (i.index()<j.index())
// ++i;
// else
// ++j;
// }
// return res;
// }
//
// Scalar sum() const
// {
// Scalar res = 0;
// for (typename Derived::InnerIterator iter(*this,0); iter; ++iter)
// {
// res += iter.value();
// }
// return res;
// }
protected:
bool m_isRValue;

View File

@@ -150,7 +150,7 @@ struct ei_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,ColMajor>
float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f);
res.resize(rows, cols);
res.startFill(ratioRes*rows*cols);
res.startFill(int(ratioRes*rows*cols));
for (int j=0; j<cols; ++j)
{
// let's do a more accurate determination of the nnz ratio for the current column j of res

View File

@@ -0,0 +1,70 @@
// 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>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_SPARSEREDUX_H
#define EIGEN_SPARSEREDUX_H
template<typename Derived, int Vectorization, int Unrolling>
struct ei_sum_impl<Derived, Vectorization, Unrolling, IsSparse>
{
typedef typename Derived::Scalar Scalar;
static Scalar run(const Derived& mat)
{
ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
Scalar res = 0;
for (int j=0; j<mat.outerSize(); ++j)
for (typename Derived::InnerIterator iter(mat,j); iter; ++iter)
res += iter.value();
return res;
}
};
template<typename Derived1, typename Derived2, int Vectorization, int Unrolling>
struct ei_dot_impl<Derived1, Derived2, Vectorization, Unrolling, IsSparse>
{
typedef typename Derived1::Scalar Scalar;
static Scalar run(const Derived1& v1, const Derived2& v2)
{
ei_assert(v1.size()>0 && "you are using a non initialized vector");
typename Derived1::InnerIterator i(v1,0);
typename Derived2::InnerIterator j(v2,0);
Scalar res = 0;
while (i && j)
{
if (i.index()==j.index())
{
res += i.value() * ei_conj(j.value());
++i; ++j;
}
else if (i.index()<j.index())
++i;
else
++j;
}
return res;
}
};
#endif // EIGEN_SPARSEREDUX_H

View File

@@ -272,6 +272,28 @@ class SparseVector
return s;
}
// this specialized version does not seems to be faster
// Scalar dot(const SparseVector& other) const
// {
// int i=0, j=0;
// Scalar res = 0;
// asm("#begindot");
// while (i<nonZeros() && j<other.nonZeros())
// {
// if (m_data.index(i)==other.m_data.index(j))
// {
// res += m_data.value(i) * ei_conj(other.m_data.value(j));
// ++i; ++j;
// }
// else if (m_data.index(i)<other.m_data.index(j))
// ++i;
// else
// ++j;
// }
// asm("#enddot");
// return res;
// }
/** Destructor */
inline ~SparseVector() {}
};

View File

@@ -114,13 +114,13 @@ struct SluMatrix : SuperMatrix
}
};
template<typename Scalar, int Rows, int Cols, int StorageOrder, int MRows, int MCols>
struct SluMatrixMapHelper<Matrix<Scalar,Rows,Cols,StorageOrder,MRows,MCols> >
template<typename Scalar, int Rows, int Cols, int Options, int MRows, int MCols>
struct SluMatrixMapHelper<Matrix<Scalar,Rows,Cols,Options,MRows,MCols> >
{
typedef Matrix<Scalar,Rows,Cols,StorageOrder,MRows,MCols> MatrixType;
typedef Matrix<Scalar,Rows,Cols,Options,MRows,MCols> MatrixType;
static void run(MatrixType& mat, SluMatrix& res)
{
assert(StorageOrder==0 && "row-major dense matrices is not supported by SuperLU");
ei_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU");
res.setStorageType(SLU_DN);
res.setScalarType<Scalar>();
res.Mtype = SLU_GE;
@@ -139,7 +139,7 @@ struct SluMatrixMapHelper<SparseMatrix<Scalar,Flags> >
typedef SparseMatrix<Scalar,Flags> MatrixType;
static void run(MatrixType& mat, SluMatrix& res)
{
if (Flags&RowMajorBit)
if ((Flags&RowMajorBit)==RowMajorBit)
{
res.setStorageType(SLU_NR);
res.nrow = mat.cols();
@@ -181,7 +181,7 @@ template<typename Scalar, int Flags>
SparseMatrix<Scalar,Flags> SparseMatrix<Scalar,Flags>::Map(SluMatrix& sluMat)
{
SparseMatrix res;
if (Flags&RowMajorBit)
if ((Flags&RowMajorBit)==RowMajorBit)
{
assert(sluMat.Stype == SLU_NR);
res.m_innerSize = sluMat.ncol;
@@ -276,7 +276,7 @@ class SparseLU<MatrixType,SuperLU> : public SparseLU<MatrixType>
mutable UMatrixType m_u;
mutable IntColVectorType m_p;
mutable IntRowVectorType m_q;
mutable SparseMatrix<Scalar> m_matrix;
mutable SluMatrix m_sluA;
mutable SuperMatrix m_sluL, m_sluU;
@@ -423,7 +423,7 @@ void SparseLU<MatrixType,SuperLU>::extractData() const
int* Ucol = m_u._outerIndexPtr();
int* Urow = m_u._innerIndexPtr();
Scalar* Uval = m_u._valuePtr();
Ucol[0] = 0;
Ucol[0] = 0;
@@ -434,7 +434,7 @@ void SparseLU<MatrixType,SuperLU>::extractData() const
istart = L_SUB_START(fsupc);
nsupr = L_SUB_START(fsupc+1) - istart;
upper = 1;
/* for each column in the supernode */
for (int j = fsupc; j < L_FST_SUPC(k+1); ++j)
{

View File

@@ -0,0 +1,73 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2009 Alex Stapleton <alex.stapleton@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_STDVECTOR_H
#define EIGEN_STDVECTOR_H
#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
typedef Eigen::aligned_allocator<value_type> allocator_type; \
typedef vector<value_type, allocator_type > unaligned_base; \
typedef typename unaligned_base::size_type size_type; \
typedef typename unaligned_base::iterator iterator; \
explicit vector(const allocator_type& __a = allocator_type()) : unaligned_base(__a) {} \
vector(const vector& c) : unaligned_base(c) {} \
vector(size_type num, const value_type& val = value_type()) : unaligned_base(num, val) {}\
vector(iterator start, iterator end) : unaligned_base(start, end) {} \
vector& operator=(const vector& __x) { \
unaligned_base::operator=(__x); \
return *this; \
}
template <typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols, typename _Alloc>
class vector<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>, _Alloc>
: public vector<Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >,
Eigen::aligned_allocator<Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> > > >
{
public:
typedef Eigen::ei_unaligned_type<Eigen::Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> > value_type;
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
};
template <typename _Scalar, int _Dim, typename _Alloc>
class vector<Eigen::Transform<_Scalar,_Dim>, _Alloc>
: public vector<Eigen::ei_unaligned_type<Eigen::Transform<_Scalar,_Dim> >,
Eigen::aligned_allocator<Eigen::ei_unaligned_type<Eigen::Transform<_Scalar,_Dim> > > >
{
public:
typedef Eigen::ei_unaligned_type<Eigen::Transform<_Scalar,_Dim> > value_type;
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
};
template <typename _Scalar, typename _Alloc>
class vector<Eigen::Quaternion<_Scalar>, _Alloc>
: public vector<Eigen::ei_unaligned_type<Eigen::Quaternion<_Scalar> >,
Eigen::aligned_allocator<Eigen::ei_unaligned_type<Eigen::Quaternion<_Scalar> > > >
{
public:
typedef Eigen::ei_unaligned_type<Eigen::Quaternion<_Scalar> > value_type;
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
};
#endif // EIGEN_STDVECTOR_H

View File

@@ -0,0 +1,76 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2009 Alex Stapleton <alex.stapleton@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_UNALIGNEDTYPE_H
#define EIGEN_UNALIGNEDTYPE_H
template<typename aligned_type> class ei_unaligned_type;
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class ei_unaligned_type<Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >
: public Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>
{
public:
typedef Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> aligned_base;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
resize(other.rows(), other.cols());
ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
}
};
template<typename _Scalar, int _Dim>
class ei_unaligned_type<Transform<_Scalar,_Dim> >
: public Transform<_Scalar,_Dim>
{
public:
typedef Transform<_Scalar,_Dim> aligned_base;
typedef typename aligned_base::MatrixType MatrixType;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<MatrixType,MatrixType,NoVectorization>::run(this->matrix(), other.matrix());
}
};
template<typename _Scalar>
class ei_unaligned_type<Quaternion<_Scalar> >
: public Quaternion<_Scalar>
{
public:
typedef Quaternion<_Scalar> aligned_base;
typedef typename aligned_base::Coefficients Coefficients;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<Coefficients,Coefficients,NoVectorization>::run(this->coeffs(), other.coeffs());
}
};
#endif // EIGEN_UNALIGNEDTYPE_H

View File

@@ -21,9 +21,9 @@ int main(int argc, char* argv[])
{
int size = SIZE * 8;
int size2 = size * size;
Scalar* a = ei_aligned_malloc<Scalar>(size2);
Scalar* b = ei_aligned_malloc<Scalar>(size2+4)+1;
Scalar* c = ei_aligned_malloc<Scalar>(size2);
Scalar* a = ei_aligned_new<Scalar>(size2);
Scalar* b = ei_aligned_new<Scalar>(size2+4)+1;
Scalar* c = ei_aligned_new<Scalar>(size2);
for (int i=0; i<size; ++i)
{

View File

@@ -16,10 +16,10 @@ if (EIGEN2_INCLUDE_DIR)
else (EIGEN2_INCLUDE_DIR)
find_path(EIGEN2_INCLUDE_DIR NAMES Eigen/Core
PATHS
PATH_SUFFIXES eigen2
HINTS
${INCLUDE_INSTALL_DIR}
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen2
)
include(FindPackageHandleStandardArgs)

View File

@@ -38,16 +38,16 @@ public :
typedef typename f77_interface_base<real>::gene_vector gene_vector;
static void free_matrix(gene_matrix & A, int N){
ei_aligned_free(A, 0);
ei_aligned_delete(A);
}
static void free_vector(gene_vector & B){
ei_aligned_free(B, 0);
ei_aligned_delete(B);
}
static inline void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
int N = A_stl.size();
A = ei_aligned_malloc<real>(N*N);
A = ei_aligned_new<real>(N*N);
for (int j=0;j<N;j++)
for (int i=0;i<N;i++)
A[i+N*j] = A_stl[j][i];
@@ -55,7 +55,7 @@ public :
static inline void vector_from_stl(gene_vector & B, stl_vector & B_stl){
int N = B_stl.size();
B = ei_aligned_malloc<real>(N);
B = ei_aligned_new<real>(N);
for (int i=0;i<N;i++)
B[i] = B_stl[i];
}

View File

@@ -3,19 +3,29 @@ if (SUPERLU_INCLUDES AND SUPERLU_LIBRARIES)
set(SUPERLU_FIND_QUIETLY TRUE)
endif (SUPERLU_INCLUDES AND SUPERLU_LIBRARIES)
find_path(SUPERLU_INCLUDES
NAMES
superlu/supermatrix.h
PATHS
$ENV{SUPERLUDIR}
${INCLUDE_INSTALL_DIR}
)
find_package(BLAS)
find_library(SUPERLU_LIBRARIES superlu PATHS $ENV{SUPERLUDIR} ${LIB_INSTALL_DIR})
if(BLAS_FOUND)
find_path(SUPERLU_INCLUDES
NAMES
superlu/supermatrix.h
PATHS
$ENV{SUPERLUDIR}
${INCLUDE_INSTALL_DIR}
)
if(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARIES} -lgfortran)
endif(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
find_library(SUPERLU_LIBRARIES superlu PATHS $ENV{SUPERLUDIR} ${LIB_INSTALL_DIR})
if(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARIES} -lgfortran)
endif(SUPERLU_LIBRARIES AND CMAKE_COMPILER_IS_GNUCXX)
if(SUPERLU_LIBRARIES)
set(SUPERLU_LIBRARIES ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
endif(SUPERLU_LIBRARIES)
endif(BLAS_FOUND)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SUPERLU DEFAULT_MSG

View File

@@ -0,0 +1,38 @@
namespace Eigen {
/** \page FixedSizeVectorizable Fixed-size vectorizable Eigen objects
The goal of this page is to explain what we mean by "fixed-size vectorizable".
\section summary Executive Summary
An Eigen object is called "fixed-size vectorizable" if it has fixed size and that size is a multiple of 16 bytes.
Examples include:
\li Eigen::Vector2d
\li Eigen::Vector4d
\li Eigen::Vector4f
\li Eigen::Matrix2d
\li Eigen::Matrix2f
\li Eigen::Matrix4d
\li Eigen::Matrix4f
\li Eigen::Transform3d
\li Eigen::Transform3f
\li Eigen::Quaterniond
\li Eigen::Quaternionf
\section explanation Explanation
First, "fixed-size" should be clear: an Eigen object has fixed size if its number of rows and its number of columns are fixed at compile-time. So for example Matrix3f has fixed size, but MatrixXf doesn't (the opposite of fixed-size is dynamic-size).
The array of coefficients of a fixed-size Eigen object is a plain "static array", it is not dynamically allocated. For example, the data behind a Matrix4f is just a "float array[16]".
Fixed-size objects are typically very small, which means that we want to handle them with zero runtime overhead -- both in terms of memory usage and of speed.
Now, vectorization (both SSE and AltiVec) works with 128-bit packets. Moreover, for performance reasons, these packets need to be have 128-bit alignment.
So it turns out that the only way that fixed-size Eigen objects can be vectorized, is if their size is a multiple of 128 bits, or 16 bytes. Eigen will then request 16-byte alignment for these object, and henceforth rely on these objects being aligned so no runtime check for alignment is performed.
*/
}

View File

@@ -101,10 +101,10 @@ with size=50, rows=50, columns=1.
Here is this constructor:
\code
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_malloc<T>(size)), m_rows(rows) {}
inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_new<T>(size)), m_rows(rows) {}
\endcode
Here, the \a m_data member is the actual array of coefficients of the matrix. As you see, it is dynamically allocated. Rather than calling new[] or malloc(), as you can see, we have our own ei_aligned_malloc defined in src/Core/util/Memory.h. What it does is that if vectorization is enabled, then it uses a platform-specific call to allocate a 128-bit-aligned array, as that is very useful for vectorization with both SSE2 and AltiVec. If vectorization is disabled, it amounts to the standard new[].
Here, the \a m_data member is the actual array of coefficients of the matrix. As you see, it is dynamically allocated. Rather than calling new[] or malloc(), as you can see, we have our own ei_aligned_new defined in src/Core/util/Memory.h. What it does is that if vectorization is enabled, then it uses a platform-specific call to allocate a 128-bit-aligned array, as that is very useful for vectorization with both SSE2 and AltiVec. If vectorization is disabled, it amounts to the standard new[].
As you can see, the constructor also sets the \a m_rows member to \a size. Notice that there is no \a m_columns member: indeed, in this partial specialization of ei_matrix_storage, we know the number of columns at compile-time, since the _Cols template parameter is different from Dynamic. Namely, in our case, _Cols is 1, which is to say that our vector is just a matrix with 1 column. Hence, there is no need to store the number of columns as a runtime variable.

40
doc/PassingByValue.dox Normal file
View File

@@ -0,0 +1,40 @@
namespace Eigen {
/** \page PassingByValue Passing Eigen objects by value to functions
Passing objects by value is almost always a very bad idea in C++, as this means useless copies, and one should pass them by reference instead.
With Eigen, this is even more important: passing \ref FixedSizeVectorizable "fixed-size vectorizable Eigen objects" by value is not only inefficient, it can be illegal or make your program crash! And the reason is that these Eigen objects have alignment modifiers that aren't respected when they are passed by value.
So for example, a function like this, where v is passed by value:
\code
void my_function(Eigen::Vector2d v);
\endcode
needs to be rewritten as follows, passing v by reference:
\code
void my_function(const Eigen::Vector2d& v);
\endcode
Likewise if you have a class having a Eigen object as member:
\code
struct Foo
{
Eigen::Vector2d v;
};
void my_function(Foo v);
\endcode
This function also needs to be rewritten like this:
\code
void my_function(const Foo& v);
\endcode
Note that on the other hand, there is no problem with functions that return objects by value.
*/
}

52
doc/StlContainers.dox Normal file
View File

@@ -0,0 +1,52 @@
namespace Eigen {
/** \page StlContainers Using STL Containers with Eigen
\b Table \b of \b contents
- \ref summary
- \ref allocator
- \ref vector
\section summary Executive summary
Using STL containers on \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" requires taking the following two steps:
\li A 16-byte-aligned allocator must be used. Eigen does provide one ready for use: aligned_allocator.
\li If you want to use the std::vector container, you need to #include <Eigen/StdVector>.
These issues arise only with \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types". For other Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers.
\section allocator Using an aligned allocator
STL containers take an optional template parameter, the allocator type. When using STL containers on \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types", you need tell the container to use an allocator that will always allocate memory at 16-byte-aligned locations. Fortunately, Eigen does provide such an allocator: Eigen::aligned_allocator.
For example, instead of
\code
std::map<int, Eigen::Vector4f>
\endcode
you need to use
\code
std::map<int, Eigen::Vector4f, std::less<int>, Eigen::aligned_allocator<Eigen::Vector4f> >
\endcode
Note that here, the 3rd parameter "std::less<int>" is just the default value, we only had to specify it because we needed to specify the allocator type, that is the 4th parameter.
\section vector The case of std::vector
The situation with std::vector was even worse (explanation below) so we had to specialize it for Eigen types. The upside is that our specialization takes care of specifying the aligned allocator, so you don't need to worry about it. All you need to do is to #include <Eigen/StdVector>.
So as soon as you have
\code
#include<Eigen/StdVector>
\endcode
you can simply use
\code
std::vector<Eigen::Vector4f>
\endcode
without having to worry about anything.
<span class="note">\b Explanation: The resize() method of std::vector takes a value_type argument (defaulting to value_type()). So with std::vector<Eigen::Vector4f>, some Eigen::Vector4f objects will be passed by value, which discards any alignment modifiers, so a Eigen::Vector4f can be created at an unaligned location. In order to avoid that, the only solution we saw was to specialize std::vector to make it work on a slight modification of, here, Eigen::Vector4f, that is able to deal properly with this situation.
</span>
*/
}

View File

@@ -0,0 +1,149 @@
namespace Eigen {
/** \page StructHavingEigenMembers Structures Having Eigen Members
\b Table \b of \b contents
- \ref summary
- \ref what
- \ref how
- \ref why
- \ref movetotop
- \ref bugineigen
- \ref conditional
\section summary Executive Summary
If you define a structure having members of \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types", you must overload its "operator new" so that it generates 16-bytes-aligned pointers. Fortunately, Eigen provides you with a macro EIGEN_MAKE_ALIGNED_OPERATOR_NEW that does that for you.
\section what What kind of code needs to be changed?
The kind of code that needs to be changed is this:
\code
class Foo
{
...
Eigen::Vector2d v;
...
};
...
Foo *foo = new Foo;
\endcode
In other words: you have a class that has as a member a \ref FixedSizeVectorizable "fixed-size vectorizable Eigen object", and then you dynamically create an object of that class.
\section how How should such code be modified?
Very easy, you just need to put a EIGEN_MAKE_ALIGNED_OPERATOR_NEW macro in a public part of your class, like this:
\code
class Foo
{
...
Eigen::Vector2d v;
...
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
...
Foo *foo = new Foo;
\endcode
This macro makes "new Foo" always return an aligned pointer.
\section why Why is this needed?
OK let's say that your code looks like this:
\code
class Foo
{
...
Eigen::Vector2d v;
...
};
...
Foo *foo = new Foo;
\endcode
A Eigen::Vector2d consists of 2 doubles, which is 128 bits. Which is exactly the size of a SSE packet, which makes it possible to use SSE for all sorts of operations on this vector. But SSE instructions (at least the ones that Eigen uses, which are the fast ones) require 128-bit alignment. Otherwise you get a segmentation fault.
For this reason, Eigen takes care by itself to require 128-bit alignment for Eigen::Vector2d, by doing two things:
\li Eigen requires 128-bit alignment for the Eigen::Vector2d's array (of 2 doubles). With GCC, this is done with a __attribute__ ((aligned(16))).
\li Eigen overloads the "operator new" of Eigen::Vector2d so it will always return 128-bit aligned pointers.
Thus, normally, you don't have to worry about anything, Eigen handles alignment for you...
... except in one case. When you have a class Foo like above, and you dynamically allocate a new Foo as above, then, since Foo doesn't have aligned "operator new", the returned pointer foo is not necessarily 128-bit aligned.
The alignment attribute of the member v is then relative to the start of the class, foo. If the foo pointer wasn't aligned, then foo->v won't be aligned either!
The solution is to let class Foo have an aligned "operator new", as we showed in the previous section.
\section movetotop Should I then put all the members of Eigen types at the beginning of my class?
No, that's not needed. Since Eigen takes care of declaring 128-bit alignment, all members that need it are automatically 128-bit aligned relatively to the class. So when you have code like
\code
class Foo
{
double x;
Eigen::Vector2d v;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
\endcode
it will work just fine. You do \b not need to rewrite it as
\code
class Foo
{
Eigen::Vector2d v;
double x;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
\endcode
\section dynamicsize What about dynamic-size matrices and vectors?
Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with fixed-size matrices and vectors.
\section bugineigen So is this a bug in Eigen?
No, it's not our bug. It's more like an inherent problem of the C++ language -- though it must be said that any other existing language probably has the same problem. The problem is that there is no way that you can specify an aligned "operator new" that would propagate to classes having you as member data.
\section conditional What if I want to do this conditionnally (depending on template parameters) ?
For this situation, we offer the macro EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign). It will generate aligned operators like EIGEN_MAKE_ALIGNED_OPERATOR_NEW if NeedsToAlign is true. It will generate operators with the default alignment if NeedsToAlign is false.
Example:
\code
template<int n> class Foo
{
typedef Eigen::Matrix<float,n,1> Vector;
enum { NeedsToAlign = (sizeof(Vector)%16)==0 };
...
Vector v;
...
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
};
...
Foo<4> *foo4 = new Foo<4>; // foo4 is guaranteed to be 128bit-aligned
Foo<3> *foo3 = new Foo<3>; // foo3 has only the system default alignment guarantee
\endcode
*/
}

View File

@@ -26,7 +26,7 @@ So in the basic example,
\code matrix1 = matrix2 + matrix3; \endcode
Eigen chooses lazy evaluation. Thus the arrays are traversed only once, producing optimized code. If you really want to force immediate evaluation, use \link MatrixBase::eval() eval() \endlink:
Eigen chooses lazy evaluation. Thus the arrays are traversed only once, producing optimized code. If you really want to force immediate evaluation, use \link MatrixBase::eval() eval()\endlink:
\code matrix1 = (matrix2 + matrix3).eval(); \endcode
@@ -36,25 +36,25 @@ Here is now a more involved example:
Eigen chooses lazy evaluation at every stage in that example, which is clearly the correct choice. In fact, lazy evaluation is the "default choice" and Eigen will choose it except in a few circumstances.
<b>The first circumstance</b> in which Eigen chooses immediate evaluation, is when it sees an assignment <tt>a = b;</tt> and the expression \c b has the evaluate-before-assigning \link flags flag \endlink. The most importat example of such an expression is the \link Product matrix product expression \endlink. For example, when you do
<b>The first circumstance</b> in which Eigen chooses immediate evaluation, is when it sees an assignment <tt>a = b;</tt> and the expression \c b has the evaluate-before-assigning \link flags flag\endlink. The most important example of such an expression is the \link Product matrix product expression\endlink. For example, when you do
\code matrix = matrix * matrix; \endcode
Eigen first evaluates <tt>matrix * matrix</tt> into a temporary matrix, and then copies it into the original \c matrix. This guarantees a correct result as we saw above that lazy evaluation gives wrong results with matrix products. It also doesn't cost much, as the cost of the matrix product itself is much higher.
What if you know what you are doing and want to force lazy evaluation? Then use \link MatrixBase::lazy() .lazy() \endlink instead. Here is an example:
What if you know what you are doing and want to force lazy evaluation? Then use \link MatrixBase::lazy() .lazy()\endlink instead. Here is an example:
\code matrix1 = (matrix2 * matrix2).lazy(); \endcode
Here, since we know that matrix2 is not the same matrix as matrix1, we know that lazy evaluation is not dangerous, so we may force lazy evaluation. Concretely, the effect of lazy() here is to remove the evaluate-before-assigning \link flags flag \endlink and also the evaluate-before-nesting \link flags flag \endlink which we now discuss.
Here, since we know that matrix2 is not the same matrix as matrix1, we know that lazy evaluation is not dangerous, so we may force lazy evaluation. Concretely, the effect of lazy() here is to remove the evaluate-before-assigning \link flags flag\endlink and also the evaluate-before-nesting \link flags flag\endlink which we now discuss.
<b>The second circumstance</b> in which Eigen chooses immediate evaluation, is when it sees a nested expression such as <tt>a + b</tt> where \c b is already an expression having the evaluate-before-nesting \link flags flag \endlink. Again, the most importat example of such an expression is the \link Product matrix product expression \endlink. For example, when you do
<b>The second circumstance</b> in which Eigen chooses immediate evaluation, is when it sees a nested expression such as <tt>a + b</tt> where \c b is already an expression having the evaluate-before-nesting \link flags flag\endlink. Again, the most important example of such an expression is the \link Product matrix product expression\endlink. For example, when you do
\code matrix1 = matrix2 + matrix3 * matrix4; \endcode
the product <tt>matrix3 * matrix4</tt> gets evaluated immediately into a temporary matrix. Indeed, experiments showed that it is often beneficial for performance to evaluate immediately matrix products when they are nested into bigger expressions.
Again, \link MatrixBase::lazy() .lazy() \endlink can be used to force lazy evaluation here.
Again, \link MatrixBase::lazy() .lazy()\endlink can be used to force lazy evaluation here.
<b>The third circumstance</b> in which Eigen chooses immediate evaluation, is when its cost model shows that the total cost of an operation is reduced if a sub-expression gets evaluated into a temporary. Indeed, in certain cases, an intermediate result is sufficiently costly to compute and is reused sufficiently many times, that is worth "caching". Here is an example:

View File

@@ -2,124 +2,75 @@ namespace Eigen {
/** \page UnalignedArrayAssert Explanation of the assertion on unaligned arrays
Hello! You are seeing this webpage because your program terminated on an assertion failure like this one:
<pre>
my_program: path/to/eigen2/Eigen/src/Core/MatrixStorage.h:44:
Eigen::ei_matrix_array<T, Size, MatrixOptions, Align>::ei_matrix_array()
[with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]:
Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion
is explained here: http://eigen.tuxfamily.org/api/UnalignedArrayAssert.html
**** READ THIS WEB PAGE !!! ****"' failed.
</pre>
There are 3 known causes for this issue. Please read on to understand them and learn how to fix them.
\b Table \b of \b contents
- \ref what
- \ref how
- \ref why
- \ref movetotop
- \ref bugineigen
- \ref c1
- \ref c2
- \ref c3
- \ref explanation
<hr>
\section c1 Cause 1: Structures having Eigen objects as members
\section what What kind of code made this assertion fail?
If you saw the assertion failure that links to this page, then you probably have done something like that in your code:
If you have code like this,
\code
class Foo
{
...
//...
Eigen::Vector2d v;
...
//...
};
...
//...
Foo *foo = new Foo;
\endcode
In other words: you have probably in your code a class that has as a member a vectorizable fixed-size Eigen object, and you then dynamically allocated an object of that class.
then you need to read this separate page: \ref StructHavingEigenMembers "Structures Having Eigen Members".
By "vectorizable fixed-size Eigen object" we mean an Eigen matrix or vector of fixed size, and whose size is a multiple of 128 bits. Examples include:
\li Eigen::Vector2d
\li Eigen::Vector4d
\li Eigen::Vector4f
\li Eigen::Matrix2d
\li Eigen::Matrix2f
\li Eigen::Matrix4d
\li Eigen::Matrix4f
\li Eigen::Transform3d
\li Eigen::Transform3f
Note that here, Eigen::Vector2d is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
\section how How to fix this bug?
\section c2 Cause 2: STL Containers
Very easy, you just need to let your class Foo publicly inherit Eigen::WithAlignedOperatorNew, like this:
If you use STL Containers such as std::vector, std::map, ..., with Eigen objects, like this,
\code
class Foo : public Eigen::WithAlignedOperatorNew
{
...
Eigen::Vector2d v;
...
};
...
Foo *foo = new Foo;
std::vector<Eigen::Matrix2f> my_vector;
std::map<int, Eigen::Matrix2f> my_map;
\endcode
With this, you should be out of trouble.
then you need to read this separate page: \ref StlContainers "Using STL Containers with Eigen".
\section why So can you explain what's happening here?
Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
OK let's say that your code looks like this:
\section c3 Cause 3: Passing Eigen objects by value
If some function in your code is getting an Eigen object passed by value, like this,
\code
class Foo
{
...
Eigen::Vector2d v;
...
};
...
Foo *foo = new Foo;
void func(Eigen::Vector4d v);
\endcode
A Eigen::Vector2d consists of 2 doubles, which is 128 bits. Which is exactly the size of a SSE packet, which makes it possible to use SSE for all sorts of operations on this vector. But SSE instructions (at least the ones that Eigen uses, which are the fast ones) require 128-bit alignment. Otherwise you get a segmentation fault.
then you need to read this separate page: \ref PassingByValue "Passing Eigen objects by value to functions".
For this reason, Eigen takes care by itself to require 128-bit alignment for Eigen::Vector2d, by doing two things:
\li Eigen requires 128-bit alignment for the Eigen::Vector2d's array (of 2 doubles). With GCC, this is done with a __attribute__ ((aligned(16))).
\li Eigen overloads the "operator new" of Eigen::Vector2d so it will always return 128-bit aligned pointers.
Note that here, Eigen::Vector4d is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
Thus, normally, you don't have to worry about anything, Eigen handles alignment for you...
\section explanation General explanation of this assertion
... except in one case. When you have a class Foo like above, and you dynamically allocate a new Foo as above, then, since Foo doesn't have aligned "operator new", the returned pointer foo is not necessarily 128-bit aligned.
\ref FixedSizeVectorizable "fixed-size vectorizable Eigen objects" must absolutely be created at 16-byte-aligned locations, otherwise SIMD instructions adressing them will crash.
The alignment attribute of the member v is then relative to the start of the class, foo. If the foo pointer wasn't aligned, then foo->v won't be aligned either!
Eigen normally takes care of these alignment issues for you, by setting an alignment attribute on them and by overloading their "operator new".
The solution is to let class Foo have an aligned "operator new", as we showed in the previous section.
\section movetotop Should I then put all the members of Eigen types at the beginning of my class?
No, that's not needed. Since Eigen takes care of declaring 128-bit alignment, all members that need it are automatically 128-bit aligned relatively to the class. So when you have code like
\code
class Foo : public Eigen::WithAlignedOperatorNew
{
double x;
Eigen::Vector2d v;
};
\endcode
it will work just fine. You do \b not need to rewrite it as
\code
class Foo : public Eigen::WithAlignedOperatorNew
{
Eigen::Vector2d v;
double x;
};
\endcode
\section dynamicsize What about dynamic-size matrices and vectors?
Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this bug. The bug discussed here is only with fixed-size matrices and vectors.
\section bugineigen So is this a bug in Eigen?
No, it's not our bug. It's more like an inherent problem of the C++ language -- though it must be said that any other existing language probably has the same problem. The problem is that there is no way that you can specify an aligned "operator new" that would propagate to classes having you as member data.
However there are a few corner cases where these alignment settings get overridden: they are the possible causes for this assertion.
*/

View File

@@ -0,0 +1,4 @@
Vector3d v(3,2,4);
Vector3d w(5,4,2);
v.cwise() /= w;
cout << v << endl;

View File

@@ -0,0 +1,4 @@
Vector3d v(1,2,3);
Vector3d w(2,3,0);
v.cwise() *= w;
cout << v << endl;

View File

@@ -7,14 +7,17 @@ else(GSL_FOUND)
endif(GSL_FOUND)
set(SPARSE_LIBS "")
set(EIGEN_TESTED_BACKENDS "")
set(EIGEN_MISSING_BACKENDS "")
find_package(Taucs)
if(TAUCS_FOUND)
add_definitions("-DEIGEN_TAUCS_SUPPORT")
include_directories(${TAUCS_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${TAUCS_LIBRARIES})
set(EIGEN_TESTED_BACKENDS ${EIGEN_TESTED_BACKENDS} Taucs)
else(TAUCS_FOUND)
message("TAUCS not found, this optional backend won't be tested")
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} Taucs)
endif(TAUCS_FOUND)
find_package(Cholmod)
@@ -22,21 +25,24 @@ if(CHOLMOD_FOUND)
add_definitions("-DEIGEN_CHOLMOD_SUPPORT")
include_directories(${CHOLMOD_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES})
set(EIGEN_TESTED_BACKENDS ${EIGEN_TESTED_BACKENDS} Cholmod)
else(CHOLMOD_FOUND)
message("CHOLMOD not found, this optional backend won't be tested")
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} Cholmod)
endif(CHOLMOD_FOUND)
if(NOT MSVC)
option(EIGEN_TEST_NO_FORTRAN "Disable Fortran" OFF)
if(NOT MSVC AND NOT EIGEN_TEST_NO_FORTRAN)
enable_language(Fortran OPTIONAL)
endif(NOT MSVC)
endif(NOT MSVC AND NOT EIGEN_TEST_NO_FORTRAN)
find_package(Umfpack)
if(UMFPACK_FOUND)
add_definitions("-DEIGEN_UMFPACK_SUPPORT")
include_directories(${UMFPACK_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES})
set(EIGEN_TESTED_BACKENDS ${EIGEN_TESTED_BACKENDS} UmfPack)
else(UMFPACK_FOUND)
message("UMFPACK not found, this optional backend won't be tested")
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} UmfPack)
endif(UMFPACK_FOUND)
find_package(SuperLU)
@@ -44,16 +50,18 @@ if(SUPERLU_FOUND)
add_definitions("-DEIGEN_SUPERLU_SUPPORT")
include_directories(${SUPERLU_INCLUDES})
set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES})
set(EIGEN_TESTED_BACKENDS ${EIGEN_TESTED_BACKENDS} SuperLU)
else(SUPERLU_FOUND)
message("SUPERLU not found, this optional backend won't be tested")
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} SuperLU)
endif(SUPERLU_FOUND)
find_package(GoogleHash)
if(GOOGLEHASH_FOUND)
add_definitions("-DEIGEN_GOOGLEHASH_SUPPORT")
include_directories(${GOOGLEHASH_INCLUDES})
set(EIGEN_TESTED_BACKENDS ${EIGEN_TESTED_BACKENDS} GoogleHash)
else(GOOGLEHASH_FOUND)
message("Google's hash library not found, those map implementations won't be tested")
set(EIGEN_MISSING_BACKENDS ${EIGEN_MISSING_BACKENDS} GoogleHash)
endif(GOOGLEHASH_FOUND)
if(CMAKE_COMPILER_IS_GNUCXX)
@@ -146,7 +154,6 @@ macro(ei_add_test testname)
endmacro(ei_add_test)
enable_testing()
if(TEST_LIB)
@@ -160,6 +167,7 @@ ei_add_test(nomalloc)
ei_add_test(mixingtypes)
ei_add_test(packetmath)
ei_add_test(unalignedassert)
ei_add_test(vectorization_logic)
ei_add_test(basicstuff)
ei_add_test(linearstructure)
ei_add_test(cwiseop)
@@ -186,6 +194,60 @@ ei_add_test(hyperplane)
ei_add_test(parametrizedline)
ei_add_test(alignedbox)
ei_add_test(regression)
ei_add_test(sparse_basic " " "${SPARSE_LIBS}")
ei_add_test(stdvector)
ei_add_test(sparse_basic)
ei_add_test(sparse_vector)
ei_add_test(sparse_solvers " " "${SPARSE_LIBS}")
# print a summary of the different options
message("************************************************************")
message("*** Eigen's unit tests configuration summary ***")
message("************************************************************")
if(GSL_FOUND)
message("Comparison with GSL: ON")
else(GSL_FOUND)
message("Comparison with GSL: OFF")
endif(GSL_FOUND)
message("Enabled backends: ${EIGEN_TESTED_BACKENDS}")
message("Disabled backends: ${EIGEN_MISSING_BACKENDS}")
if(EIGEN_TEST_SSE2)
message("SSE2: ON")
else(EIGEN_TEST_SSE2)
message("SSE2: AUTO")
endif(EIGEN_TEST_SSE2)
if(EIGEN_TEST_SSE3)
message("SSE3: ON")
else(EIGEN_TEST_SSE3)
message("SSE3: AUTO")
endif(EIGEN_TEST_SSE3)
if(EIGEN_TEST_SSSE3)
message("SSSE3: ON")
else(EIGEN_TEST_SSSE3)
message("SSSE3: AUTO")
endif(EIGEN_TEST_SSSE3)
if(EIGEN_TEST_ALTIVEC)
message("Altivec: ON")
else(EIGEN_TEST_ALTIVEC)
message("Altivec: AUTO")
endif(EIGEN_TEST_ALTIVEC)
if(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
message("Explicit vec: OFF")
else(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
message("Explicit vec: AUTO")
endif(EIGEN_TEST_NO_EXPLICIT_VECTORIZATION)
message("CXX: ${CMAKE_CXX_COMPILER}")
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version COMMAND head -n 1 OUTPUT_VARIABLE EIGEN_CXX_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE)
message("CXX_VERSION: ${EIGEN_CXX_VERSION_STRING}")
endif(CMAKE_COMPILER_IS_GNUCXX)
message("CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
message("Sparse lib flags: ${SPARSE_LIBS}")
message("************************************************************")

View File

@@ -39,7 +39,7 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
RealScalar largerEps = test_precision<RealScalar>();
if (ei_is_same_type<RealScalar,float>::ret)
largerEps = 1e-3f;
largerEps = RealScalar(1e-3f);
MatrixType m1 = MatrixType::Random(rows, cols),
m2 = MatrixType::Random(rows, cols),

View File

@@ -48,7 +48,7 @@ template<typename BoxType> void alignedbox(const BoxType& _box)
b0.extend(p0);
b0.extend(p1);
VERIFY(b0.contains(p0*s1+(1.-s1)*p1));
VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
VERIFY(!b0.contains(p0 + (1+s1)*(p1-p0)));
(b2 = b0).extend(b1);

View File

@@ -73,6 +73,9 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
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)
@@ -87,6 +90,9 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
// VERIFY_IS_APPROX(m1.cwise().pow(0.5), m1.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

View File

@@ -24,39 +24,67 @@
#include "main.h"
// test compilation with both a struct and a class...
struct MyStruct : WithAlignedOperatorNew
void check_handmade_aligned_malloc()
{
for(int i = 1; i < 1000; i++)
{
char *p = (char*)ei_handmade_aligned_malloc(i);
VERIFY(size_t(p)%16==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(size_t(p)%16==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(size_t(p)%16==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++)
{
float *p = ei_aligned_stack_new(float,i);
VERIFY(size_t(p)%16==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_stack_delete(float,p,i);
}
}
// test compilation with both a struct and a class...
struct MyStruct
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
char dummychar;
Vector4f avec;
};
class MyClassA : public WithAlignedOperatorNew
{
public:
char dummychar;
Vector4f avec;
};
// ..as well as with some other base classes
class MyBaseClass
{
public:
char dummychar;
float afloat;
};
class MyClassB : public WithAlignedOperatorNew, public MyBaseClass
{
public:
char dummychar;
Vector4f avec;
};
class MyClassC : public MyBaseClass, public WithAlignedOperatorNew
class MyClassA
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
char dummychar;
Vector4f avec;
};
@@ -70,8 +98,12 @@ template<typename T> void check_dynaligned()
void test_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());
#ifdef EIGEN_VECTORIZE
for (int i=0; i<g_repeat*100; ++i)
{
CALL_SUBTEST( check_dynaligned<Vector4f>() );
@@ -85,8 +117,6 @@ void test_dynalloc()
{
MyStruct foo0; VERIFY(size_t(foo0.avec.data())%16==0);
MyClassA fooA; VERIFY(size_t(fooA.avec.data())%16==0);
MyClassB fooB; VERIFY(size_t(fooB.avec.data())%16==0);
MyClassC fooC; VERIFY(size_t(fooC.avec.data())%16==0);
}
// dynamic allocation, single object
@@ -94,12 +124,8 @@ void test_dynalloc()
{
MyStruct *foo0 = new MyStruct(); VERIFY(size_t(foo0->avec.data())%16==0);
MyClassA *fooA = new MyClassA(); VERIFY(size_t(fooA->avec.data())%16==0);
MyClassB *fooB = new MyClassB(); VERIFY(size_t(fooB->avec.data())%16==0);
MyClassC *fooC = new MyClassC(); VERIFY(size_t(fooC->avec.data())%16==0);
delete foo0;
delete fooA;
delete fooB;
delete fooC;
}
// dynamic allocation, array
@@ -108,29 +134,8 @@ void test_dynalloc()
{
MyStruct *foo0 = new MyStruct[N]; VERIFY(size_t(foo0->avec.data())%16==0);
MyClassA *fooA = new MyClassA[N]; VERIFY(size_t(fooA->avec.data())%16==0);
MyClassB *fooB = new MyClassB[N]; VERIFY(size_t(fooB->avec.data())%16==0);
MyClassC *fooC = new MyClassC[N]; VERIFY(size_t(fooC->avec.data())%16==0);
delete[] foo0;
delete[] fooA;
delete[] fooB;
delete[] fooC;
}
// std::vector
for (int i=0; i<g_repeat*100; ++i)
{
std::vector<Vector4f, ei_new_allocator<Vector4f> > vecs(N);
for (int j=0; j<N; ++j)
{
VERIFY(size_t(vecs[j].data())%16==0);
}
std::vector<MyStruct,ei_new_allocator<MyStruct> > foos(N);
for (int j=0; j<N; ++j)
{
VERIFY(size_t(foos[j].avec.data())%16==0);
}
}
#endif // EIGEN_VECTORIZE
}

View File

@@ -52,7 +52,6 @@ template<typename Scalar> void geometry(void)
if (ei_is_same_type<Scalar,float>::ret)
largeEps = 1e-3f;
Quaternionx q1, q2;
Vector3 v0 = Vector3::Random(),
v1 = Vector3::Random(),
v2 = Vector3::Random();
@@ -69,6 +68,13 @@ template<typename Scalar> void geometry(void)
(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().dot(u0), Scalar(1));
VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));

View File

@@ -31,8 +31,8 @@ template<typename VectorType> void map_class(const VectorType& m)
int size = m.size();
// test Map.h
Scalar* array1 = ei_aligned_malloc<Scalar>(size);
Scalar* array2 = ei_aligned_malloc<Scalar>(size);
Scalar* array1 = ei_aligned_new<Scalar>(size);
Scalar* array2 = ei_aligned_new<Scalar>(size);
Scalar* array3 = new Scalar[size+1];
Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
@@ -45,8 +45,8 @@ template<typename VectorType> void map_class(const VectorType& m)
VERIFY_IS_APPROX(ma1, ma2);
VERIFY_IS_APPROX(ma1, ma3);
ei_aligned_free(array1, size);
ei_aligned_free(array2, size);
ei_aligned_delete(array1, size);
ei_aligned_delete(array2, size);
delete[] array3;
}
@@ -57,8 +57,8 @@ template<typename VectorType> void map_static_methods(const VectorType& m)
int size = m.size();
// test Map.h
Scalar* array1 = ei_aligned_malloc<Scalar>(size);
Scalar* array2 = ei_aligned_malloc<Scalar>(size);
Scalar* array1 = ei_aligned_new<Scalar>(size);
Scalar* array2 = ei_aligned_new<Scalar>(size);
Scalar* array3 = new Scalar[size+1];
Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
@@ -71,8 +71,8 @@ template<typename VectorType> void map_static_methods(const VectorType& m)
VERIFY_IS_APPROX(ma1, ma2);
VERIFY_IS_APPROX(ma1, ma3);
ei_aligned_free(array1, size);
ei_aligned_free(array2, size);
ei_aligned_delete(array1, size);
ei_aligned_delete(array2, size);
delete[] array3;
}

View File

@@ -57,9 +57,7 @@ void test_meta()
VERIFY(( ei_is_same_type<float,ei_unpointer<float* const >::type >::ret));
VERIFY(ei_meta_sqrt<1>::ret == 1);
#define VERIFY_META_SQRT(X) \
std::cerr << ei_meta_sqrt<X>::ret << " == " << int(ei_sqrt(double(X))) << "\n"; \
VERIFY(ei_meta_sqrt<X>::ret == int(ei_sqrt(double(X))))
#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);

View File

@@ -25,28 +25,13 @@
// this hack is needed to make this file compiles with -pedantic (gcc)
#define throw(X)
// discard vectorization since the global operator new is not called in that case
#define EIGEN_DONT_VECTORIZE 1
// discard stack allocation as that too bypasses the global operator new
// 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"
void* operator new[] (size_t n)
{
ei_assert(false && "operator new should never be called with fixed size path");
// the following is in case assertion are disabled
std::cerr << "operator new should never be called with fixed size path" << std::endl;
exit(2);
void* p = malloc(n);
return p;
}
void operator delete[](void* p) throw()
{
free(p);
}
template<typename MatrixType> void nomalloc(const MatrixType& m)
{
/* this test check no dynamic memory allocation are issued with fixed-size matrices

View File

@@ -58,7 +58,7 @@ initSparse(double density,
std::vector<Vector2i>* zeroCoords = 0,
std::vector<Vector2i>* nonzeroCoords = 0)
{
sparseMat.startFill(refMat.rows()*refMat.cols()*density);
sparseMat.startFill(int(refMat.rows()*refMat.cols()*density));
for(int j=0; j<refMat.cols(); j++)
{
for(int i=0; i<refMat.rows(); i++)
@@ -89,4 +89,28 @@ initSparse(double density,
sparseMat.endFill();
}
template<typename Scalar> void
initSparse(double density,
Matrix<Scalar,Dynamic,1>& refVec,
SparseVector<Scalar>& sparseVec,
std::vector<int>* zeroCoords = 0,
std::vector<int>* nonzeroCoords = 0)
{
sparseVec.reserve(int(refVec.size()*density));
sparseVec.setZero();
for(int i=0; i<refVec.size(); i++)
{
Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
if (v!=Scalar(0))
{
sparseVec.fill(i) = v;
if (nonzeroCoords)
nonzeroCoords->push_back(i);
}
else if (zeroCoords)
zeroCoords->push_back(i);
refVec[i] = v;
}
}
#endif // EIGEN_TESTSPARSE_H

92
test/sparse_vector.cpp Normal file
View File

@@ -0,0 +1,92 @@
// 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>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "sparse.h"
template<typename Scalar> void sparse_vector(int rows, int cols)
{
double densityMat = std::max(8./(rows*cols), 0.01);
double densityVec = std::max(8./float(rows), 0.1);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
typedef SparseVector<Scalar> SparseVectorType;
typedef SparseMatrix<Scalar> SparseMatrixType;
Scalar eps = 1e-6;
SparseMatrixType m1(rows,cols);
SparseVectorType v1(rows), v2(rows), v3(rows);
DenseMatrix refM1 = DenseMatrix::Zero(rows, cols);
DenseVector refV1 = DenseVector::Random(rows),
refV2 = DenseVector::Random(rows),
refV3 = DenseVector::Random(rows);
std::vector<int> zerocoords, nonzerocoords;
initSparse<Scalar>(densityVec, refV1, v1, &zerocoords, &nonzerocoords);
initSparse<Scalar>(densityMat, refM1, m1);
initSparse<Scalar>(densityVec, refV2, v2);
initSparse<Scalar>(densityVec, refV3, v3);
Scalar s1 = ei_random<Scalar>();
// test coeff and coeffRef
for (unsigned int i=0; i<zerocoords.size(); ++i)
{
VERIFY_IS_MUCH_SMALLER_THAN( v1.coeff(zerocoords[i]), eps );
VERIFY_RAISES_ASSERT( v1.coeffRef(zerocoords[i]) = 5 );
}
{
VERIFY(int(nonzerocoords.size()) == v1.nonZeros());
int j=0;
for (typename SparseVectorType::InnerIterator it(v1); it; ++it,++j)
{
VERIFY(nonzerocoords[j]==it.index());
VERIFY(it.value()==v1[it.index()]);
}
}
VERIFY_IS_APPROX(v1, refV1);
v1.coeffRef(nonzerocoords[0]) = Scalar(5);
refV1.coeffRef(nonzerocoords[0]) = Scalar(5);
VERIFY_IS_APPROX(v1, refV1);
VERIFY_IS_APPROX(v1+v2, refV1+refV2);
VERIFY_IS_APPROX(v1+v2+v3, refV1+refV2+refV3);
VERIFY_IS_APPROX(v1*s1-v2, refV1*s1-refV2);
std::cerr << v1.dot(v2) << " == " << refV1.dot(refV2) << "\n";
VERIFY_IS_APPROX(v1.dot(v2), refV1.dot(refV2));
}
void test_sparse_vector()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( sparse_vector<double>(8, 8) );
// CALL_SUBTEST( sparse_vector<std::complex<double> >(16, 16) );
CALL_SUBTEST( sparse_vector<double>(299, 535) );
}
}

163
test/stdvector.cpp Normal file
View File

@@ -0,0 +1,163 @@
// 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>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#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> 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].set(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((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(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> 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((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; 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> 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((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; i<v.size(); ++i)
{
VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
}
}
void test_stdvector()
{
// some non vectorizable fixed sizes
CALL_SUBTEST(check_stdvector_matrix(Vector2f()));
CALL_SUBTEST(check_stdvector_matrix(Matrix3f()));
CALL_SUBTEST(check_stdvector_matrix(Matrix3d()));
// some vectorizable fixed sizes
CALL_SUBTEST(check_stdvector_matrix(Matrix2f()));
CALL_SUBTEST(check_stdvector_matrix(Vector4f()));
CALL_SUBTEST(check_stdvector_matrix(Matrix4f()));
CALL_SUBTEST(check_stdvector_matrix(Matrix4d()));
// some dynamic sizes
CALL_SUBTEST(check_stdvector_matrix(MatrixXd(1,1)));
CALL_SUBTEST(check_stdvector_matrix(VectorXd(20)));
CALL_SUBTEST(check_stdvector_matrix(RowVectorXf(20)));
CALL_SUBTEST(check_stdvector_matrix(MatrixXcf(10,10)));
// some Transform
CALL_SUBTEST(check_stdvector_transform(Transform2f()));
CALL_SUBTEST(check_stdvector_transform(Transform3f()));
CALL_SUBTEST(check_stdvector_transform(Transform3d()));
//CALL_SUBTEST(check_stdvector_transform(Transform4d()));
// some Quaternion
CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
CALL_SUBTEST(check_stdvector_quaternion(Quaternionf()));
}

205
test/testsuite.cmake Normal file
View File

@@ -0,0 +1,205 @@
####################################################################
#
# Usage:
# - create a new folder, let's call it cdash
# - in that folder, do:
# ctest -S path/to/eigen2/test/testsuite.cmake[,option1=value1[,option2=value2]]
#
# Options:
# - EIGEN_CXX: compiler, eg.: g++-4.2
# default: default c++ compiler
# - EIGEN_SITE: eg, INRIA-Bdx_pc-gael, or the name of the contributor, etc.
# default: hostname
# - EIGEN_BUILD_STRING: a string which identify the system/compiler. It should be formed like that:
# <OS_name>-<OS_version>-<arch>-<compiler-version>
# with:
# <OS_name> = opensuse, debian, osx, windows, cygwin, freebsd, solaris, etc.
# <OS_version> = 11.1, XP, vista, leopard, etc.
# <arch> = i386, x86_64, ia64, powerpc, etc.
# <compiler-version> = gcc-4.3.2, icc-11.0, MSVC-2008, etc.
# - EIGEN_EXPLICIT_VECTORIZATION: novec, SSE2, Altivec
# default: SSE2 for x86_64 systems, novec otherwise
# - EIGEN_CMAKE_DIR: path to cmake executable
# - EIGEN_MODE: dashboard model, can be Experimental, Nightly, or Continuous
# default: Nightly
# - EIGEN_WORK_DIRECTORY: directory used to download the source files and make the builds
# default: folder which contains this script
# - CTEST_SOURCE_DIRECTORY: path to eigen's src (use a new and empty folder, not the one you are working on)
# default: <EIGEN_WORK_DIRECTORY>/src
# - CTEST_BINARY_DIRECTORY: build directory
# default: <EIGEN_WORK_DIRECTORY>/nightly-<EIGEN_CXX>
#
# Here is an example running several compilers on a linux system:
# #!/bin/bash
# EIGEN_ARCH=`uname -m`
# EIGEN_SITE=`hostname`
# EIGEN_OS_VERSION=opensuse-11.1
# COMMON=/home/gael/Coding/eigen2/test/testsuite.cmake,EIGEN_WORK_DIRECTORY=/home/gael/Coding/eigen2/cdash,EIGEN_SITE=$EIGEN_SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$EIGEN_OS_VERSION-$EIGEN_ARCH
# ctest -S $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4
# ctest -S $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1
# ctest -S $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3
# ctest -S $COMMON-icc-11.0,EIGEN_CXX=icpc
#
####################################################################
# process the arguments
set(ARGLIST ${CTEST_SCRIPT_ARG})
while(${ARGLIST} MATCHES ".+.*")
# pick first
string(REGEX MATCH "([^,]*)(,.*)?" DUMMY ${ARGLIST})
SET(TOP ${CMAKE_MATCH_1})
# remove first
string(REGEX MATCHALL "[^,]*,(.*)" DUMMY ${ARGLIST})
SET(ARGLIST ${CMAKE_MATCH_1})
# decompose as a pair key=value
string(REGEX MATCH "([^=]*)(=.*)?" DUMMY ${TOP})
SET(KEY ${CMAKE_MATCH_1})
string(REGEX MATCH "[^=]*=(.*)" DUMMY ${TOP})
SET(VALUE ${CMAKE_MATCH_1})
# set the variable to the specified value
if(VALUE)
SET(${KEY} ${VALUE})
else(VALUE)
SET(${KEY} ON)
endif(VALUE)
endwhile(${ARGLIST} MATCHES ".+.*")
####################################################################
# Automatically set some user variables if they have not been defined manually
####################################################################
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
if(NOT EIGEN_SITE)
site_name(EIGEN_SITE)
endif(NOT EIGEN_SITE)
if(NOT EIGEN_CMAKE_DIR)
SET(EIGEN_CMAKE_DIR "")
endif(NOT EIGEN_CMAKE_DIR)
if(NOT EIGEN_BUILD_STRING)
# let's try to find all information we need to make the build string ourself
# OS
# if(CYGWIN)
# SET(EIGEN_OS_VERSION cygwin)
# elseif(WIN32)
# SET(EIGEN_OS_VERSION windows)
# elseif(UNIX)
# SET(EIGEN_OS_VERSION unix)
# elseif(APPLE)
# SET(EIGEN_OS_VERSION osx)
# else(CYGWIN)
build_name(EIGEN_OS_VERSION)
# endif(CYGWIN)
# arch
set(EIGEN_ARCH ${CMAKE_SYSTEM_PROCESSOR})
if(WIN32)
set(EIGEN_ARCH $ENV{PROCESSOR_ARCHITECTURE})
else(WIN32)
execute_process(COMMAND uname -m OUTPUT_VARIABLE EIGEN_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
endif(WIN32)
set(EIGEN_BUILD_STRING ${EIGEN_OS_VERSION}${EIGEN_ARCH}-${EIGEN_CXX})
endif(NOT EIGEN_BUILD_STRING)
if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
set(EIGEN_BUILD_STRING ${EIGEN_BUILD_STRING}-${EIGEN_EXPLICIT_VECTORIZATION})
endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
if(NOT EIGEN_WORK_DIRECTORY)
set(EIGEN_WORK_DIRECTORY ${CTEST_SCRIPT_DIRECTORY})
endif(NOT EIGEN_WORK_DIRECTORY)
if(NOT CTEST_SOURCE_DIRECTORY)
SET (CTEST_SOURCE_DIRECTORY "${EIGEN_WORK_DIRECTORY}/src")
endif(NOT CTEST_SOURCE_DIRECTORY)
if(NOT CTEST_BINARY_DIRECTORY)
SET (CTEST_BINARY_DIRECTORY "${EIGEN_WORK_DIRECTORY}/nightly_${EIGEN_CXX}")
endif(NOT CTEST_BINARY_DIRECTORY)
if(NOT EIGEN_MODE)
set(EIGEN_MODE Nightly)
endif(NOT EIGEN_MODE)
## mandatory variables (the default should be ok in most cases):
SET (CTEST_CVS_COMMAND "svn")
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} co svn://anonsvn.kde.org/home/kde/trunk/kdesupport/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
# which ctest command to use for running the dashboard
SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")
# what cmake command to use for configuring this dashboard
SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_BUILD_TESTS=on ")
####################################################################
# The values in this section are optional you can either
# have them or leave them commented out
####################################################################
# this make sure we get consistent outputs
SET($ENV{LC_MESSAGES} "en_EN")
# should ctest wipe the binary tree before running
SET(CTEST_START_WITH_EMPTY_BINARY_DIRECTORY TRUE)
SET(CTEST_BACKUP_AND_RESTORE TRUE)
# this is the initial cache to use for the binary tree, be careful to escape
# any quotes inside of this string if you use it
if(WIN32)
#message(SEND_ERROR "win32")
set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=nmake")
SET (CTEST_INITIAL_CACHE "
MAKECOMMAND:STRING=nmake -i
CMAKE_MAKE_PROGRAM:FILEPATH=nmake
CMAKE_GENERATOR:INTERNAL=NMake Makefiles
BUILDNAME:STRING=${EIGEN_BUILD_STRING}
SITE:STRING=${EIGEN_SITE}
")
else(WIN32)
SET (CTEST_INITIAL_CACHE "
BUILDNAME:STRING=${EIGEN_BUILD_STRING}
SITE:STRING=${EIGEN_SITE}
")
endif(WIN32)
# MAKECOMMAND:STRING=nmake -i
# CMAKE_MAKE_PROGRAM:FILEPATH=make
# CMAKE_GENERATOR:INTERNAL=Makefiles
SET (CTEST_INITIAL_CACHE "
BUILDNAME:STRING=opensuse-11_1-x86_64-${EIGEN_CXX}
SITE:STRING=pc-gael
CVSCOMMAND:FILEPATH=/usr/bin/svn"
)
# set any extra environment variables to use during the execution of the script here:
if(EIGEN_CXX)
set(CTEST_ENVIRONMENT "CXX=${EIGEN_CXX}")
endif(EIGEN_CXX)
if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
if(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON")
elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE3)
set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON")
elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES Altivec)
set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_ALTIVEC=ON")
elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES novec)
set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON")
else(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
message(FATAL_ERROR "Invalid value for EIGEN_EXPLICIT_VECTORIZATION (${EIGEN_EXPLICIT_VECTORIZATION}), must be: novec, SSE2, SSE3, Altivec")
endif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)

View File

@@ -55,21 +55,30 @@ struct Bad6
Matrix<double, 3, 4> m; // bad: same reason
};
struct Good7 : Eigen::WithAlignedOperatorNew
struct Good7
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Vector2d m;
float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects
};
struct Good8 : Eigen::WithAlignedOperatorNew
struct Good8
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
float f; // try the f at first -- the EIGEN_ALIGN_128 attribute of m should make that still work
Matrix4f m;
};
struct Good9
{
Matrix<float,2,2,Matrix_DontAlign> m; // good: no alignment requested
Matrix<float,2,2,DontAlign> m; // good: no alignment requested
float f;
};
template<bool Align> struct Depends
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align)
Vector2d m;
float f;
};
@@ -89,7 +98,7 @@ void check_unalignedassert_bad()
float buf[sizeof(T)+16];
float *unaligned = buf;
while((reinterpret_cast<size_t>(unaligned)&0xf)==0) ++unaligned; // make sure unaligned is really unaligned
T *x = new(static_cast<void*>(unaligned)) T;
T *x = ::new(static_cast<void*>(unaligned)) T;
x->~T();
}
@@ -104,6 +113,8 @@ void unalignedassert()
check_unalignedassert_good<Good7>();
check_unalignedassert_good<Good8>();
check_unalignedassert_good<Good9>();
check_unalignedassert_good<Depends<true> >();
VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Depends<false> >());
}
void test_unalignedassert()

View File

@@ -0,0 +1,103 @@
// 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>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <typeinfo>
template<typename Dst, typename Src>
bool test_assign(const Dst&, const Src&, int vectorization, int unrolling)
{
return ei_assign_traits<Dst,Src>::Vectorization==vectorization
&& ei_assign_traits<Dst,Src>::Unrolling==unrolling;
}
template<typename Xpr>
bool test_sum(const Xpr&, int vectorization, int unrolling)
{
return ei_sum_traits<Xpr>::Vectorization==vectorization
&& ei_sum_traits<Xpr>::Unrolling==unrolling;
}
void test_vectorization_logic()
{
#ifdef EIGEN_VECTORIZE
VERIFY(test_assign(Vector4f(),Vector4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Vector4f(),Vector4f()+Vector4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Vector4f(),Vector4f().cwise() * Vector4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Matrix4f(),Matrix4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Matrix4f(),Matrix4f()+Matrix4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Matrix4f(),Matrix4f().cwise() * Matrix4f(),
InnerVectorization,CompleteUnrolling));
VERIFY(test_assign(Matrix<float,16,16>(),Matrix<float,16,16>()+Matrix<float,16,16>(),
InnerVectorization,InnerUnrolling));
VERIFY(test_assign(Matrix<float,16,16,DontAlign>(),Matrix<float,16,16>()+Matrix<float,16,16>(),
NoVectorization,InnerUnrolling));
VERIFY(test_assign(Matrix<float,6,2>(),Matrix<float,6,2>().cwise() / Matrix<float,6,2>(),
LinearVectorization,CompleteUnrolling));
VERIFY(test_assign(Matrix<float,17,17>(),Matrix<float,17,17>()+Matrix<float,17,17>(),
NoVectorization,InnerUnrolling));
VERIFY(test_assign(Matrix<float,4,4>(),Matrix<float,17,17>().block<4,4>(2,3)+Matrix<float,17,17>().block<4,4>(10,4),
NoVectorization,CompleteUnrolling));
VERIFY(test_assign(MatrixXf(10,10),MatrixXf(20,20).block(10,10,2,3),
SliceVectorization,NoUnrolling));
VERIFY(test_sum(VectorXf(10),
LinearVectorization,NoUnrolling));
VERIFY(test_sum(Matrix<float,5,2>(),
NoVectorization,CompleteUnrolling));
VERIFY(test_sum(Matrix<float,6,2>(),
LinearVectorization,CompleteUnrolling));
VERIFY(test_sum(Matrix<float,16,16>(),
LinearVectorization,NoUnrolling));
VERIFY(test_sum(Matrix<float,16,16>().block<4,4>(1,2),
NoVectorization,CompleteUnrolling));
VERIFY(test_sum(Matrix<float,16,16>().block<8,1>(1,2),
LinearVectorization,CompleteUnrolling));
VERIFY(test_sum(Matrix<double,7,3>(),
NoVectorization,CompleteUnrolling));
#endif // EIGEN_VECTORIZE
}